android 蓝牙4.0连接3个GATT传感器,数据不稳定
    这个bug困扰很久了,求万能的CSDN解答。

    手头的项目,用android平板的蓝牙4.0连接三个BLE蓝牙传感器。获取传感器的数据。

    蓝牙传感器以每包/20ms的速度发送数据,每包数据16字节。(3个传感器总数据量,不大吧)

    在onCharacteristicChanged()回调方法中,获取数据,并发送给业务端。

    那么问题来了,3个传感器数据理论上是平均的发过来的;

    但是实际接收中,不定期的,某一个传感器会出现3-4s的数据丢失(onCharacteristicChanged()方法没有回调),

    单独连接一个传感器,不会出现数据丢失。但是连接3个以后就会出现。

    传感器硬件先排除,内存也并没有溢出,蓝牙连接没有断开。只是会出现“数据丢失”。

    怀疑是蓝牙4.0底层的问题,或者数据处理队列的问题?不太懂。有没有了解的大神解答下。挺着急的。

    gatt1 = btdevice.connectGatt(context, false, new BluetoothGattCallback() {});

                如有没说完全的,请提问,我继续补充。非常感谢

1个回答

楼主的这个问题解决了吗?解决了的话能给我些意见吗?我写蓝牙的数据的时候,设备那端会有时候出现数据丢失,写的太快会丢失的很严重,所以我一般延迟几百ms,但是有时候还是会丢失!!我觉得写和读的数据太快了会堵塞,从而导致数据丢失!

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Android 蓝牙4.0怎么接收设备传输的数据
一直在研究Android蓝牙4.0的app,现在已经借到设备了,设备的低功耗蓝牙4.0能够连接上,但是手机Android的app连接设备之后就没了反应,我也不知道有没有在接收数据,我是在蓝牙设置界面进行的一系列修改。下面是重要的代码: ``` 蓝牙设置界面是个fragment,即BtSetFragment.java 在网上查到的是在GattCallback 中的onCharacteristicChanged用来接收数据, private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback(){ @Override public void onConnectionStateChange(BluetoothGatt gatt,int status,int newState){ String intentAction; if(newState == BluetoothProfile.STATE_CONNECTED){ intentionAction = ACTION_GATT_CONNECTED; broadcastUpdate(intentAction); Log.i(TAG,"Connected to GATT Server"); Log.i(TAG,"Attemping to start service discovery:" + mBLuetoothGatt.diacoverServices()); }else if(newState == BluetoothProfile.STATE_DISCONNECTED){ intentAction = ACTION_GATT_DISCONNECTION; Log.i(TAG,"Disconnected from GATT server."); broadcastUpdate(intentAction); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic){ Log.d(TAG,"onCharacteristicChanged ,接收数据"); broadcastUpdate(ACTION_DATA_AVAILABLE,characteristic); } }; ``` 在网上下载的蓝牙4.0的demo中的函数DeviceScanActivity.java , DeviceControlActivity.java , BluetoothLeService.java这三个函数中的主要的函数都移到了BtSetFragment.java中,不知道怎么去接收并显示接到的蓝牙设备上的数据,求各个大神
android开发BLE蓝牙时蓝牙连接不稳定会自动断开重连
搜索、通讯均正常,只是连接不正常 public void onCreate(){ super.onCreate(); // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to // BluetoothAdapter through BluetoothManager. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); // Checks if Bluetooth is supported on the device. if (mBluetoothAdapter == null) { Toast.makeText(this, "没有蓝牙", Toast.LENGTH_SHORT).show(); stopSelf(); return; } if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){ Toast.makeText(this, "不支持BLE", Toast.LENGTH_SHORT).show(); stopSelf(); return; } } @Override public void onDestroy(){ if(mBluetoothGatt != null){ mBluetoothGatt.close(); } mBluetoothGatt = null; super.onDestroy(); } @Override public boolean onUnbind(Intent intent){ if(mBluetoothGatt != null){ mBluetoothGatt.close(); } mBluetoothGatt = null; return super.onUnbind(intent); } // Device scan callback. private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { String str = device.getName() + "|" + device.getAddress(); LogUtil.d(TAG, "get BluetoothDevice.ACTION_FOUND:" + str); sendLocalBroadcast(ACTION_SCAN_FOUND,str); } }; public void startScan(){ Handler mHandler = new Handler(); mHandler.postDelayed(new Runnable() { @Override public void run() { stopScan(); } },SCAN_PERIOD ); LogUtil.d(TAG, "get startScan"); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); sendLocalBroadcast(ACTION_SCAN_STARTED); } public void stopScan(){ if(mScanning){ LogUtil.d(TAG, "get stopScan"); mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); sendLocalBroadcast(ACTION_SCAN_FINISHED); } } public void findService(List<BluetoothGattService> gattServices) { Log.i(TAG, "Count is:" + gattServices.size()); for (BluetoothGattService gattService : gattServices) { Log.i(TAG, gattService.getUuid().toString()); Log.i(TAG, UUID_SERVICE.toString()); if(gattService.getUuid().toString().equalsIgnoreCase(UUID_SERVICE.toString())) { List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics(); Log.i(TAG, "Count is:" + gattCharacteristics.size()); for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { if(gattCharacteristic.getUuid().toString().equalsIgnoreCase(UUID_NOTIFY.toString())) { Log.i(TAG, gattCharacteristic.getUuid().toString()); Log.i(TAG, UUID_NOTIFY.toString()); mNotifyCharacteristic = gattCharacteristic; setCharacteristicNotification(gattCharacteristic, true); //broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); return; } } } } } // Implements callback methods for GATT events that the app cares about. For example, // connection change and services discovered. //设备连接 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { String intentAction; Log.i(TAG, "oldStatus=" + status + " NewStates=" + newState); if(status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { intentAction = ACTION_CONNECTED; sendLocalBroadcast(intentAction); Log.i(TAG, "Connected to GATT server."); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_DISCONNECTED; mBluetoothGatt.close(); mBluetoothGatt = null; Log.i(TAG, "Disconnected from GATT server."); sendLocalBroadcast(intentAction); } } } //发现服务 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { Log.w(TAG, "onServicesDiscovered received: " + status); findService(gatt.getServices()); } else { if(mBluetoothGatt.getDevice().getUuids() == null) Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { byte[] bufRecv = characteristic.getValue(); int nRecv = bufRecv.length; if(nRecv > 1024 + nReadPtr - nRecvPtr) nRecv = 1024 + nReadPtr - nRecvPtr; if(nRecv + nRecvPtr <= 1024){ System.arraycopy(bufRecv, 0, bRecv, nRecvPtr, nRecv); nRecvPtr += nRecv; } else{ System.arraycopy(bufRecv, 0, bRecv, nRecvPtr, 1024-nRecvPtr); System.arraycopy(bufRecv, 1024-nRecvPtr, bRecv, 0, nRecv - (1024-nRecvPtr)); nRecvPtr = nRecv - (1024 - nRecvPtr); } sendLocalBroadcast(ACTION_DATA_RECV); } } /** * 发送数据后的回调 * @param gatt * @param characteristic * @param status */ @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.e(TAG, "OnCharacteristicWrite"); } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor bd, int status) { Log.e(TAG, "onDescriptorRead"); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { byte[] bufRecv = characteristic.getValue(); int nRecv = bufRecv.length; if(nRecv > 1024 + nReadPtr - nRecvPtr) nRecv = 1024 + nReadPtr - nRecvPtr; if(nRecv + nRecvPtr <= 1024){ System.arraycopy(bufRecv, 0, bRecv, nRecvPtr, nRecv); nRecvPtr += nRecv; } else{ System.arraycopy(bufRecv, 0, bRecv, nRecvPtr, 1024-nRecvPtr); System.arraycopy(bufRecv, 1024-nRecvPtr, bRecv, 0, nRecv - (1024-nRecvPtr)); nRecvPtr = nRecv - (1024 - nRecvPtr); } sendLocalBroadcast(ACTION_DATA_RECV); Log.e(TAG, "onCharacteristicChanged"); } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor bd, int status) { Log.e(TAG, "onDescriptorWrite"); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int a, int b) { Log.e(TAG, "onReadRemoteRssi"); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int a) { Log.e(TAG, "onReliableWriteCompleted"); } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { Log.e(TAG, "onMtuChanged"); } }; public boolean connect(final String address){ if (mBluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if (device == null) { Log.w(TAG, "Device not found. Unable to connect."); return false; } // We want to directly connect to the device, so we are setting the autoConnect // parameter to false. if(mBluetoothGatt != null) { mBluetoothGatt.close(); mBluetoothGatt = null; } mBluetoothGatt = device.connectGatt(this, false, mGattCallback); Log.d(TAG, "Trying to create a new connection."); return true; } public void disconnect(){ if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.disconnect(); } @Override public int read(byte[] data) { int readLen = data.length; int bufLen; int retLen; if(nRecvPtr >= nReadPtr) bufLen = nRecvPtr - nReadPtr; else bufLen = nRecvPtr + 1024 - nReadPtr; if(readLen <= bufLen) retLen = readLen; else retLen = bufLen; if(nReadPtr + retLen < 1024){ System.arraycopy(bRecv, nReadPtr, data,0,retLen); nReadPtr += retLen; } else{ System.arraycopy(bRecv, nReadPtr, data, 0, 1024-nReadPtr); System.arraycopy(bRecv, 0, data, 1024-nReadPtr, retLen - (1024-nReadPtr)); nReadPtr = retLen-(1024-nReadPtr); } return retLen; } public byte[] write(byte[] data){ mNotifyCharacteristic.setValue(data/*strValue.getBytes()*/); mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic); LogUtil.i(TAG, "12154123164512332465451218451231654561233545612"); //return data.length; return data; } public final void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { byte[] value = characteristic.getValue(); Log.d(TAG, "onCharacteristicChanged: " + value); String s0 = Integer.toHexString(value[0] & 0xFF); String s = Integer.toHexString(value[1] & 0xFF); Log.d(TAG, "onCharacteristicChanged: " + s0 + "、" + s); for (byte b : value) { Log.d(TAG, "onCharacteristicChanged: " + b); } } /** * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} * callback. * * @param characteristic The characteristic to read from. */ public void readCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.readCharacteristic(characteristic); } /** * Enables or disables notification on a give characteristic. * * @param characteristic Characteristic to act on. * @param enabled If true, enable notification. False otherwise. */ public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); /* // This is specific to Heart Rate Measurement. if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { BluetoothGattDescriptor descriptor = characteristic.getDescriptor( UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } */ } /** * Retrieves a list of supported GATT services on the connected device. This should be * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully. * * @return A {@code List} of supported services. */ public List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; return mBluetoothGatt.getServices(); } } ``` ```
蓝牙4.0一主两从通信,其中一个从节点断开,怎样通知另一个从节点?
蓝牙一主两从连接好以后,其中一个从节点断开,主节点发送0x0c告知另外一个从节点,代码如下 ```case GAP_LINK_TERMINATED_EVENT: { simpleBLEState = BLE_STATE_IDLE; uint8 connectionhandle[2] = {pEvent->linkTerminate.connectionHandle >> 8, pEvent->linkTerminate.connectionHandle}; simpleBLEConnHandle[connectionhandle[1]] = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; simpleBLECharHdl = 0; simpleBLEProcedureInProgress = FALSE; LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING_VALUE( "Reason:", pEvent->linkTerminate.reason, 10, HAL_LCD_LINE_2 ); attWriteReq_t req; req.handle = 0x0035; req.len = 1; //req.offset = 0; req.sig = 0; req.cmd = 0; //osal_memcpy(req.value,ValueBuf,SIMPLEPROFILE_CHAR6_LEN); req.value[0] = 0x0C; //HalUARTWrite(0,&req.value[0],1); GATT_WriteCharValue( ShangweiConnectHandle, &req, simpleBLETaskId ); //uint8 success = GATT_WriteCharValue( ShangweiConnectHandle, &req, simpleBLETaskId ); //HalUARTWrite(0,&success,8); } break; ``` 想在这个事件里面通知另外一个从节点,但是貌似发不出去,应该怎么通知呢?
大学课程设计,编写蓝牙透传app时候,再发送一个信息蓝牙就断开连接
如题,我最近在做课程设计,题目是基于STM32的一个猫屋设计,主要是一个PWM风扇控制,和一个远程投喂功能。 再加个基于BT05的蓝牙透传APP。APP做到一半,PWM风扇做好了,但是想加个定时远程投喂加不上,思路是定时中断STM32,从而达到投喂功能。 1. 遇到的问题:APP能设置温度的上下限,读取实时温度,上下限温度。但是再想读取一个投喂间隔或者设置投喂间隔就会自动断开蓝牙连接![图片说明](https://img-ask.csdn.net/upload/201905/07/1557219048_675317.jpg) 这是我的APP界面。就是如果读取投喂间隔或者按最后一个按钮——设置投喂间隔,就会断开蓝牙,返回扫描蓝牙界面。 请各位前辈指教。我不知道怎么修改。 下面是我的DeviceCnotrolActivity.java的代码。谢谢。 ``` /* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.bluetooth.le; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ExpandableListView; import android.widget.TextView; import android.widget.Toast; /** * For a given BLE device, this Activity provides the user interface to connect, display data, * and display GATT services and characteristics supported by the device. The Activity * communicates with {@code BluetoothLeService}, which in turn interacts with the * Bluetooth LE API. */ public class DeviceControlActivity extends Activity { private final static String TAG = DeviceControlActivity.class.getSimpleName(); public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME"; public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS"; private TextView mConnectionState; private TextView mDataField; private TextView mDataTemptured;//显示温度 private TextView mSetTemptured;//设置温度 private TextView mSetLTemptured;//设置温度 下限 private TextView mFenSuRang;//风扇档位 private String mDeviceName; private String mDeviceAddress; private ExpandableListView mGattServicesList; private BluetoothLeService mBluetoothLeService; private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); private boolean mConnected = false; private BluetoothGattCharacteristic mNotifyCharacteristic; boolean connect_status_bit=false; private final String LIST_NAME = "NAME"; private final String LIST_UUID = "UUID"; private final String g_TitleName = "智能温度控制设计"; private final String g_EndByte= "0E"; private final String g_SetHADDR = "0A0B02"; private final String g_SetLADDR = "0A0B03"; private Handler mHandler; // Stops scanning after 10 seconds. private static final long SCAN_PERIOD = 1000; private int i = 0; private int TIME = 1000; // Code to manage Service lifecycle. private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); if (!mBluetoothLeService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } // Automatically connects to the device upon successful start-up initialization. mBluetoothLeService.connect(mDeviceAddress); } @Override public void onServiceDisconnected(ComponentName componentName) { mBluetoothLeService = null; } }; // Handles various events fired by the Service. // ACTION_GATT_CONNECTED: connected to a GATT server. // ACTION_GATT_DISCONNECTED: disconnected from a GATT server. // ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services. // ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read // or notification operations. private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { //mConnected = true; connect_status_bit=true; invalidateOptionsMenu(); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { mConnected = false; updateConnectionState(R.string.disconnected); connect_status_bit=false; show_view(false); invalidateOptionsMenu(); clearUI(); } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { // Show all the supported services and characteristics on the user interface. displayGattServices(mBluetoothLeService.getSupportedGattServices()); } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); } } }; // If a given GATT characteristic is selected, check for supported features. This sample // demonstrates 'Read' and 'Notify' features. See // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete // list of supported characteristic features. private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { return false; } }; private void clearUI() { //mGattServicesList.setAdapter((SimpleExpandableListAdapter) null); mDataField.setText(R.string.no_data); } Button send_button; //发送上限温度按键 Button send_Lowbutton; //发送下限温度按键 Button send_feedbutton; //发送投喂按键 Button enable_button; Button IBeacon_set_button; EditText txd_txt,uuid_1001_ed; EditText txd_txtLowTempture; //下限显示文本 EditText txd_txtfeedtime; //投喂间隔显示文本 EditText ibeacon_uuid; EditText mayjor_txt,minor_txt; EditText dev_Name; Button name_button; EditText password_ed;//密码值 Button password_enable_bt;//密码开关 Button password_wrt;//密码写入Button Button adv_time1,adv_time2,adv_time3,adv_time4; boolean pass_en=false; Button clear_button; private Button IO_H_button,IO_L_button;//out io Timer timer = new Timer(); void show_view( boolean p ) { if(p){ send_button.setEnabled(true); send_Lowbutton.setEnabled(true); send_feedbutton.setEnabled(true); }else{ send_button.setEnabled(false); send_Lowbutton.setEnabled(false); send_feedbutton.setEnabled(false); } } public void delay(int ms){ try { Thread.currentThread(); Thread.sleep(ms); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gatt_services_characteristics); final Intent intent = getIntent(); mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME); mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS); // Sets up UI references. ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress); //mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list); // mGattServicesList.setOnChildClickListener(servicesListClickListner); mConnectionState = (TextView) findViewById(R.id.connection_state); // mDataField = (TextView) findViewById(R.id.data_value); mDataTemptured = (TextView) findViewById(R.id.rx_Tempture); mSetTemptured= (TextView) findViewById(R.id.ARM_Tempture); mSetLTemptured= (TextView) findViewById(R.id.L_Tempture); mFenSuRang= (TextView) findViewById(R.id.rx_FenRang); send_button=(Button)findViewById(R.id.tx_SetHbutton);//send data 1002 send_button.setOnClickListener(listener);//设置监听 send_Lowbutton = (Button)findViewById(R.id.tx_SetLbutton);//send data 1002 send_Lowbutton.setOnClickListener(listener);//设置监听 send_feedbutton=(Button)findViewById(R.id.tx_SetFbutton);//send data 1002 send_feedbutton.setOnClickListener(listener);//设置监听 // clear_button=(Button)findViewById(R.id.clear_button);//send data 1002 // clear_button.setOnClickListener(listener);//设置监听 txd_txt=(EditText)findViewById(R.id.tx_text);//1002 data txd_txt.setText("28"); txd_txtLowTempture=(EditText)findViewById(R.id.tx_dispLTemptuer);//1002 data txd_txtLowTempture.setText("15"); // rx_data_id_1=(EditText)findViewById(R.id.rx_data_id_1);//1002 data // rx_data_id_1.setText(""); show_view(false); mHandler = new Handler(); timer.schedule(task, 1000, 1000); // 1s后执行task,经过1s再次执行 boolean sg; getActionBar().setTitle(g_TitleName); // getActionBar().setDisplayHomeAsUpEnabled(true); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); sg = bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); //getActionBar().setTitle( "="+BluetoothLeService ); //mDataField.setText("="+sg ); updateConnectionState(R.string.connecting);//更新连接状态 } Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 1) { //tvShow.setText(Integer.toString(i++)); //scanLeDevice(true); if (mBluetoothLeService != null) { if( mConnected==false ) { updateConnectionState(R.string.connecting); final boolean result = mBluetoothLeService.connect(mDeviceAddress); Log.d(TAG, "Connect request result=" + result); } } } super.handleMessage(msg); }; }; TimerTask task = new TimerTask() { @Override public void run() { // 需要做的事:发送消息 Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; Button.OnClickListener listener = new Button.OnClickListener(){//创建监听对象 public void onClick(View v){ //String strTmp="点击Button02"; //Ev1.setText(strTmp); switch( v.getId()) { case R.id.tx_SetHbutton ://uuid1002 数传通道发送数据 设置上限按钮 if( connect_status_bit ) { String tx_string=txd_txt.getText().toString().trim(); //去掉有空格 mBluetoothLeService.txxx(g_SetHADDR+tx_string+g_EndByte); }else{ //Toast.makeText(this, "Deleted Successfully!", Toast.LENGTH_LONG).show(); Toast toast = Toast.makeText(DeviceControlActivity.this, "设备没有连接!", Toast.LENGTH_SHORT); toast.show(); } break; case R.id.tx_SetLbutton ://uuid1002 数传通道发送数据 设置下限按钮 if( connect_status_bit ) { String tx_string=txd_txtLowTempture.getText().toString().trim(); //去掉有空格 mBluetoothLeService.txxx(g_SetLADDR+tx_string+g_EndByte); }else{ //Toast.makeText(this, "Deleted Successfully!", Toast.LENGTH_LONG).show(); Toast toast = Toast.makeText(DeviceControlActivity.this, "设备没有连接!", Toast.LENGTH_SHORT); toast.show(); } break; case R.id.tx_SetFbutton ://uuid1002 数传通道发送数据 设置上限按钮 if( connect_status_bit ) { String tx_string=txd_txtfeedtime.getText().toString().trim(); //去掉有空格 mBluetoothLeService.txxx(g_SetHADDR+tx_string+g_EndByte); }else{ //Toast.makeText(this, "Deleted Successfully!", Toast.LENGTH_LONG).show(); Toast toast = Toast.makeText(DeviceControlActivity.this, "设备没有连接!", Toast.LENGTH_SHORT); toast.show(); } break; // case R.id.clear_button: // { //// len_g =0; //// da = ""; //// rx_data_id_1.setText( da ); //// mDataField.setText( ""+len_g ); // }break; default : break; } } }; @Override protected void onResume() { super.onResume(); registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); if (mBluetoothLeService != null) { final boolean result = mBluetoothLeService.connect(mDeviceAddress); Log.d(TAG, "Connect request result=" + result); } } @Override protected void onPause() { super.onPause(); unregisterReceiver(mGattUpdateReceiver); } @Override protected void onDestroy() { super.onDestroy(); unbindService(mServiceConnection); mBluetoothLeService = null; timer.cancel(); timer=null; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.gatt_services, menu); if (mConnected) { menu.findItem(R.id.menu_connect).setVisible(false); menu.findItem(R.id.menu_disconnect).setVisible(true); } else { menu.findItem(R.id.menu_connect).setVisible(true); menu.findItem(R.id.menu_disconnect).setVisible(false); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.menu_connect: mBluetoothLeService.connect(mDeviceAddress); return true; case R.id.menu_disconnect: mBluetoothLeService.disconnect(); return true; case android.R.id.home: onBackPressed(); return true; } return super.onOptionsItemSelected(item); } private void updateConnectionState(final int resourceId) { runOnUiThread(new Runnable() { @Override public void run() { mConnectionState.setText(resourceId); } }); } String da=""; int len_g = 0; private void displayData( String data1 ) { //String head1,data_0; /* head1=data1.substring(0,2); data_0=data1.substring(2); */ //da = da+data1+"\n"; if( data1!=null&&data1.length()>0) { //mDataField.setText( data1 ); //len_g += data1.length()/2; //da = data1+da; //rx_data_id_1.setText( data1 ); // mDataField.setText( ""+len_g ); mDataTemptured.setText(data1.substring(4, 6)+"℃"); mSetTemptured.setText(data1.substring(6, 8)+"℃"); mSetLTemptured.setText(data1.substring(8, 10)+"℃"); mFenSuRang.setText(data1.substring(10, 12)+"档"); //rx_data_id_1.setGravity(Gravity.BOTTOM); //rx_data_id_1.setSelection(rx_data_id_1.getText().length()); } } // Demonstrates how to iterate through the supported GATT Services/Characteristics. // In this sample, we populate the data structure that is bound to the ExpandableListView // on the UI. private void displayGattServices(List<BluetoothGattService> gattServices) { if (gattServices == null) return; if( gattServices.size()>0&&mBluetoothLeService.get_connected_status( gattServices )>=4 ) { if( connect_status_bit ) { mConnected = true; show_view( true ); mBluetoothLeService.enable_JDY_ble(true); try { Thread.currentThread(); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } mBluetoothLeService.enable_JDY_ble(true); updateConnectionState(R.string.connected); }else{ //Toast.makeText(this, "Deleted Successfully!", Toast.LENGTH_LONG).show(); Toast toast = Toast.makeText(DeviceControlActivity.this, "设备没有连接!", Toast.LENGTH_SHORT); toast.show(); } } // SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter( // this, // gattServiceData, // android.R.layout.simple_expandable_list_item_2, // new String[] {LIST_NAME, LIST_UUID}, // new int[] { android.R.id.text1, android.R.id.text2 }, // gattCharacteristicData, // android.R.layout.simple_expandable_list_item_2, // new String[] {LIST_NAME, LIST_UUID}, // new int[] { android.R.id.text1, android.R.id.text2 } // ); // // mGattServicesList.setAdapter(gattServiceAdapter); } private static IntentFilter makeGattUpdateIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED); intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE); return intentFilter; } } ```
BLE的UUID是不是固定的?
请问,不同的硬件BLE设备,它们的Service和Characteristic的UUID是不是都是一样的? 最近写app做练习,在连接BLE模块时,可以正常收发信息,但是连接了另一个BLE设备时,会短暂连接后马上崩溃。下面是AS的报错, ``` E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.administrator.mi_home, PID: 5569 java.lang.RuntimeException: Error receiving broadcast Intent { act=com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED flg=0x10 } in com.example.administrator.mi_home.DeviceFragment.OneDeviceFragment$1@c064ebc at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1228) at android.os.Handler.handleCallback(Handler.java:761) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:156) at android.app.ActivityThread.main(ActivityThread.java:6523) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.UUID android.bluetooth.BluetoothGattCharacteristic.getUuid()' on a null object reference at android.bluetooth.BluetoothGatt.setCharacteristicNotification(BluetoothGatt.java:1104) at com.example.administrator.mi_home.Service.BleService.setCharacteristicNotification(BleService.java:175) at com.example.administrator.mi_home.DeviceFragment.OneDeviceFragment$1.onReceive(OneDeviceFragment.java:141) at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1218) at android.os.Handler.handleCallback(Handler.java:761)  at android.os.Handler.dispatchMessage(Handler.java:98)  at android.os.Looper.loop(Looper.java:156)  at android.app.ActivityThread.main(ActivityThread.java:6523)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)  ``` 提示有个空指针异常, ``` mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); // 关键代码 ```
android ble蓝牙广播问题!!!!!!!!!!!!!!!!!!
使用ble蓝牙开发 在写入数据之后 设备返回的数据证明发送成功了 但是在广播中也会返回数据,我这边接收不到 使用别人的demo 可以接收到数据 这里有demo 哪位大哥帮忙看看代码有没有什么问题。 ``` package com.example.andysong.nuclearradiation.Ble; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.companion.BluetoothDeviceFilter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast; import com.example.andysong.nuclearradiation.Ble.Adapter.MyAdapter; import com.example.andysong.nuclearradiation.Ble.BleTool.MyBluetoothDevice; import com.example.andysong.nuclearradiation.Ble.Entity.BleData; import com.example.andysong.nuclearradiation.R; import com.example.andysong.nuclearradiation.Uitl.Progess.DialProgress; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; public class BleActivityTest extends AppCompatActivity implements View.OnClickListener, MyAdapter.OnScan { private static final String TAG = BleActivityTest.class.getName(); private Button btn_scan; private Button btn_w; private RecyclerView rv_list; private MyAdapter myAdapter; private BluetoothAdapter bAdapter; private BluetoothGatt bluetoothGatt; private Map<String, UUID> uuidMap; //private UUID uNotify = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); //private UUID N_Notify = UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"); private UUID N_Notify = UUID.fromString("00001000-0000-1000-8000-00805f9b34fb"); //private UUID uNotify = UUID.fromString("0000ffe4-0000-1000-8000-00805f9b34fb"); private UUID uNotify = UUID.fromString("00001002-0000-1000-8000-00805f9b34fb"); //private UUID uRead = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); //private UUID uWrite = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); //private UUID N_Write = UUID.fromString("0000ffe5-0000-1000-8000-00805f9b34fb"); private UUID N_Write = UUID.fromString("00001000-0000-1000-8000-00805f9b34fb"); private static final UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString( "00002902-0000-1000-8000-00805f9b34fb"); //private UUID uWrite = UUID.fromString("0000ffe9-0000-1000-8000-00805f9b34fb"); private UUID uWrite = UUID.fromString("00001001-0000-1000-8000-00805f9b34fb"); private String READ = "read"; private String WRITE = "write"; private String NOTICE = "notice"; private Button btn_r; private Button btn_n; private Button btn_c; private DialProgress dialProgress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ble); initView(); initData(); } private void initView() { btn_scan = findViewById(R.id.btn_scan); btn_w = findViewById(R.id.btn_w); btn_r = findViewById(R.id.btn_r); btn_n = findViewById(R.id.btn_n); btn_c = findViewById(R.id.btn_c); btn_scan.setOnClickListener(this); btn_w.setOnClickListener(this); btn_r.setOnClickListener(this); btn_n.setOnClickListener(this); btn_c.setOnClickListener(this); rv_list = findViewById(R.id.rv_list); rv_list.setLayoutManager(new LinearLayoutManager(this, LinearLayout.VERTICAL, false)); myAdapter = new MyAdapter(this); myAdapter.setOnScan(this); rv_list.setAdapter(myAdapter); dialProgress = findViewById(R.id.dialprog); } private void initData() { bAdapter = BluetoothAdapter.getDefaultAdapter(); uuidMap = new HashMap<>(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_scan: scan(); break; case R.id.btn_w: writeData(); break; case R.id.btn_r: readData(); break; case R.id.btn_n: notifyData(); break; case R.id.btn_c: closeNotifyData(); break; } } /*关闭广播通知*/ private void closeNotifyData() { BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(N_Notify).getCharacteristic(uNotify); BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); bluetoothGatt.writeDescriptor(descriptor); } /*打开广播通知*/ private void notifyData() { BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(N_Notify).getCharacteristic(uNotify); boolean b = bluetoothGatt.setCharacteristicNotification(characteristic, true); int originalWriteType = characteristic.getWriteType(); BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); boolean b1 = bluetoothGatt.writeDescriptor(descriptor); characteristic.setWriteType(originalWriteType); } /*read 读取数据 返回的数据需要在监听事件接收*/ private void readData() { if (bluetoothGatt == null) { return; } BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(UUID.fromString("00001000-0000-1000-8000-00805f9b34fb")). getCharacteristic(UUID.fromString("00001001-0000-1000-8000-00805f9b34fb")); bluetoothGatt.readCharacteristic(characteristic); } /*扫描设备*/ private void scan() { if (!bAdapter.isEnabled()) { Toast.makeText(this, "请打开蓝牙", Toast.LENGTH_SHORT).show(); return; } bAdapter.startLeScan(scanCallback); btn_scan.setText("扫描中"); btn_scan.setEnabled(false); } /*扫描到新的设备*/ private BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { MyBluetoothDevice bluetoothDevice = new MyBluetoothDevice(device, rssi); addDevice(bluetoothDevice); // Log.e(TAG, "onLeScan: " + device.getAddress() + device.getName()); if (device.getAddress().equals("F6:6D:83:80:D6:8D")) { conn(bluetoothDevice); } //F6:6D:83:80:D6:8D } }; /*添加扫描的新设备*/ private void addDevice(MyBluetoothDevice bluetoothDevice) { List<MyBluetoothDevice> devices = myAdapter.getDevices(); for (MyBluetoothDevice device : devices) { if (device.getDevice().getAddress().equals(bluetoothDevice.getDevice().getAddress())) { return; } } myAdapter.upDate(bluetoothDevice); } /*item点击链接的方法*/ @Override public void conn(MyBluetoothDevice device) { bluetoothGatt = device.getDevice().connectGatt(this, false, mBluetoothGattCallback); } /*写数据 数据不会直接返回 需要在监听事件中回调*/ public void writeData() { if (bluetoothGatt == null) { return; } // bluetoothGatt.readRemoteRssi(); BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(N_Write).getCharacteristic(uWrite); //characteristic.setValue("E5015101003420"); characteristic.setValue("EF52FFFAFFFF"); //characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); bluetoothGatt.writeCharacteristic(characteristic); } /*链接状态—ready—write-*/ BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() { //链接状态更改时 @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); if (newState == BluetoothProfile.STATE_CONNECTED) { gatt.discoverServices(); //查询支持的服务 bluetoothGatt = gatt; BleActivityTest.this.runOnUiThread(new Runnable() { @Override public void run() { btn_scan.setVisibility(View.GONE); btn_w.setVisibility(View.VISIBLE); btn_r.setVisibility(View.VISIBLE); btn_n.setVisibility(View.VISIBLE); btn_c.setVisibility(View.VISIBLE); } }); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.e(TAG, "onConnectionStateChange: 断开"); BleActivityTest.this.runOnUiThread(new Runnable() { @Override public void run() { btn_scan.setEnabled(true); } }); } btn_scan.setText("扫描"); } //读取数据 @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); bluetoothGatt = gatt; if (status == BluetoothGatt.GATT_SUCCESS) { Log.e(TAG, "读取成功"); printALL(characteristic.getValue()); } else { Log.e(TAG, "读取失败"); } } //写出数据返回状态 @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); bluetoothGatt = gatt; if (status == BluetoothGatt.GATT_SUCCESS) { Log.e(TAG, "onCharacteristicWrite发送成功"); printALL(characteristic.getValue()); } else { Log.e(TAG, "onCharacteristicWrite发送失败"); } } /*一般情况是 给设备发送指令使用应该*/ @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorRead(gatt, descriptor, status); bluetoothGatt = gatt; if (status == BluetoothGatt.GATT_SUCCESS) { Log.e(TAG, "onDescriptorRead读取成功"); printALL(descriptor.getValue()); } else { Log.e(TAG, "onDescriptorRead读取失败"); } } /*一般情况是 给设备发送指令使用应该*/ @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorWrite(gatt, descriptor, status); bluetoothGatt = gatt; if (status == BluetoothGatt.GATT_SUCCESS) { Log.e(TAG, "onDescriptorWrite发送成功"); printALL(descriptor.getValue()); } else { Log.e(TAG, "onDescriptorWrite发送失败"); } } /*接收通知 广播后 接收到的数据在这里*/ @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { //super.onCharacteristicChanged(gatt, characteristic); //bluetoothGatt = gatt; byte[] value = characteristic.getValue(); try { String s=new String(value,"UTF-8"); Log.e(TAG, "onCharacteristicChanged: "+s); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } printNotify(value); } //返回信号强度的 @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status); bluetoothGatt = gatt; Log.e(TAG, "onReadRemoteRssi: " + rssi); } //返回支持的服务滴 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); bluetoothGatt = gatt; read(gatt); } }; public void read(BluetoothGatt gatt) { List<BluetoothGattService> services = gatt.getServices(); for (BluetoothGattService service : services) { Log.e(TAG, "服务: " + service.getUuid() + "-----"); List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics(); for (BluetoothGattCharacteristic characteristic : characteristics) { if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) > 0) { uuidMap.put(READ, characteristic.getUuid()); Log.e(TAG, "读写属性: " + characteristic.getUuid()); for (BluetoothGattDescriptor bluetoothGattDescriptor:characteristic.getDescriptors()){ Log.e(TAG, "蓝牙描述符+++: " + bluetoothGattDescriptor.getUuid()); } } if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) { uuidMap.put(WRITE, characteristic.getUuid()); Log.e(TAG, "写属性: " + characteristic.getUuid()); } if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { uuidMap.put(NOTICE, characteristic.getUuid()); Log.e(TAG, "通知属性: " + characteristic.getUuid()); for (BluetoothGattDescriptor bluetoothGattDescriptor : characteristic.getDescriptors()) { Log.e(TAG, "蓝牙描述符: " + bluetoothGattDescriptor.getUuid()); } } } } Set<String> strings = uuidMap.keySet(); for (String key : strings) { UUID uuid = uuidMap.get(key); Log.e(TAG, "list: " + uuid.toString()); } } private void printALL(byte[] b) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < b.length; i++) { sb.append(Integer.toHexString(b[i]) + " "); } Log.e(TAG, "printALL--------: " + sb.toString()); } private void printALL2(final byte[] b) { Log.e(TAG, "printALL2--------: " + byteToString(b)); BleActivityTest.this.runOnUiThread(new Runnable() { @Override public void run() { dialProgress.setValue2(Double.parseDouble(formatString(byteToString(b)).getData())); } }); } private void printNotify(final byte[] b) { Log.e(TAG, "printNotify--------: " + byteToString(b)); BleActivityTest.this.runOnUiThread(new Runnable() { @Override public void run() { dialProgress.setValue2(Double.parseDouble(formatString(byteToString(b)).getData())); } }); } /*显示给客户*/ private String byteToString(byte[] b) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < b.length; i++) { String s = String.valueOf(b[i]).replace("-", ""); String s1 = Integer.toHexString(Integer.valueOf(s)); if (i == 0 || i == 1) { char c = asciiToChar(Integer.valueOf(s)); sb.append(c + " "); continue; } else if (s1.length() == 1) { sb.append("0" + s1 + " "); continue; } sb.append(s1 + " "); } return sb.toString(); } /*ascii 转 字符*/ private char asciiToChar(int a) { return (char) a; } /*代码用来计算的数据*/ private BleData formatString(String v) { String value = v.replace(" ", ""); String command = value.substring(0, 2); String date = value.substring(2, 8); String company = value.substring(8, 10); String d = value.substring(10, 18); StringBuffer data = new StringBuffer(); boolean flag = true; for (int i = 0; i < d.length(); i++) { if (i == 0) { continue; } if (i % 2 != 0) { if (flag) { data.append(Integer.valueOf(d.substring(0, i + 1)) + "."); flag = false; } else { data.append(Integer.valueOf(d.substring(i - 1, i + 1))); } } } String crc = value.substring(18, value.length()); return new BleData(command, date, company, data.toString(), crc); } }; ```
Android接收arduino数据来控制打电话报错
用了android官方BLE的demo可以成功接收Arduino101板子传入的数据; 在原来的程序中直接加入打电话的代码,可以实现 ``` private void displayData(String data) { if (data != null) { mDataDisplay.setText(data); } button = (Button) findViewById(R.id.button); number=data; button.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent callIntent = new Intent(Intent.ACTION_CALL); callIntent.setData(Uri.parse("tel:000000")); if (ActivityCompat.checkSelfPermission(DeviceControlActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { return; } startActivity(callIntent); } }); ``` ———————————————————————————————— 但是如果利用接收到的数据,就出现报错No Activity found to handle Intent { act=android.intent.action.CALL } ``` private void displayData(String data) { if (data != null) { mDataDisplay.setText(data); } button = (Button) findViewById(R.id.button); number=data; button.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent callIntent = new Intent(Intent.ACTION_CALL); if(number.equals("00")) { callIntent.setData(Uri.parse("tel:000000")); }else if(number.equals("01")) { callIntent.setData(Uri.parse("tel:000001")); }else if(number.equals("02")) { callIntent.setData(Uri.parse("tel:000002")); }else if(number.equals("03")) { callIntent.setData(Uri.parse("tel:000003")); }else if(number.equals("04")) { callIntent.setData(Uri.parse("tel:000004")); }else if(number.equals("05")) { callIntent.setData(Uri.parse("tel:000005")); } if (ActivityCompat.checkSelfPermission(DeviceControlActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { return; } startActivity(callIntent); } }); ``` 日志: ``` 04-19 21:06:06.176 28375-28430/com.example.bledemo D/BluetoothLeScanner: onScanResult() - ScanResult{mDevice=98:4F:EE:0F:C5:A3, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000180f-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=BatteryMonitorSketch], mRssi=-35, mTimestampNanos=613094916898376} 04-19 21:06:06.196 28375-28399/com.example.bledemo D/ScanRecord: parseFromBytes 04-19 21:06:06.196 28375-28399/com.example.bledemo D/BluetoothLeScanner: onScanResult() - ScanResult{mDevice=98:4F:EE:0F:C5:A3, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000180f-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=BatteryMonitorSketch], mRssi=-35, mTimestampNanos=613094940227543} 04-19 21:06:06.221 28375-28399/com.example.bledemo D/ScanRecord: parseFromBytes 04-19 21:06:06.221 28375-28399/com.example.bledemo D/BluetoothLeScanner: onScanResult() - ScanResult{mDevice=98:4F:EE:0F:C5:A3, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000180f-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=BatteryMonitorSketch], mRssi=-35, mTimestampNanos=613094962124876} 04-19 21:06:06.246 28375-28375/com.example.bledemo I/System.out: ==position==0 04-19 21:06:06.246 28375-28375/com.example.bledemo D/BluetoothAdapter: stopLeScan() 04-19 21:06:06.251 28375-28375/com.example.bledemo I/Timeline: Timeline: Activity_launch_request id:com.example.bledemo time:163428963 04-19 21:06:06.266 28375-28375/com.example.bledemo D/BluetoothAdapter: stopLeScan() 04-19 21:06:06.266 28375-28375/com.example.bledemo D/BluetoothAdapter: scan not started yet 04-19 21:06:06.341 28375-28375/com.example.bledemo D/AbsListView: Get MotionRecognitionManager 04-19 21:06:06.351 28375-28375/com.example.bledemo D/Activity: performCreate Call secproduct feature valuefalse 04-19 21:06:06.351 28375-28375/com.example.bledemo D/Activity: performCreate Call debug elastic valuetrue 04-19 21:06:06.521 28375-28375/com.example.bledemo D/BluetoothGatt: connect() - device: 98:4F:EE:0F:C5:A3, auto: false 04-19 21:06:06.521 28375-28375/com.example.bledemo D/BluetoothGatt: registerApp() 04-19 21:06:06.521 28375-28375/com.example.bledemo D/BluetoothGatt: registerApp() - UUID=fd636193-9b1f-4767-b799-d2eae15bcfc0 04-19 21:06:06.561 28375-28375/com.example.bledemo D/BluetoothLeService: Trying to create a new connection. 04-19 21:06:06.561 28375-28399/com.example.bledemo D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7 04-19 21:06:06.671 28375-28388/com.example.bledemo D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=98:4F:EE:0F:C5:A3 04-19 21:06:06.676 28375-28375/com.example.bledemo I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@19af1c7c time:163429389 04-19 21:06:06.681 28375-28388/com.example.bledemo I/BluetoothLeService: Connected to GATT server. 04-19 21:06:06.681 28375-28388/com.example.bledemo D/BluetoothGatt: discoverServices() - device: 98:4F:EE:0F:C5:A3 04-19 21:06:06.686 28375-28388/com.example.bledemo I/BluetoothLeService: Attempting to start service discovery:true 04-19 21:06:06.691 28375-28388/com.example.bledemo D/BluetoothGatt: onSearchComplete() = Device=98:4F:EE:0F:C5:A3 Status=0 04-19 21:06:06.941 28375-28375/com.example.bledemo V/ActivityThread: updateVisibility : ActivityRecord{3970b103 token=android.os.BinderProxy@21371bc6 {com.example.bledemo/com.example.bledemo.DeviceScanActivity}} show : false 04-19 21:06:08.126 28375-28375/com.example.bledemo D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN 04-19 21:06:08.651 28375-28375/com.example.bledemo D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN 04-19 21:06:08.796 28375-28375/com.example.bledemo D/BluetoothGatt: setCharacteristicNotification() - uuid: 00002a19-0000-1000-8000-00805f9b34fb enable: true 04-19 21:06:10.286 28375-28375/com.example.bledemo D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN 04-19 21:06:10.366 28375-28375/com.example.bledemo D/Instrumentation: checkStartActivityResult :Intent { act=android.intent.action.CALL } 04-19 21:06:10.366 28375-28375/com.example.bledemo D/Instrumentation: checkStartActivityResult inent is instance of inent: 04-19 21:06:10.366 28375-28375/com.example.bledemo D/AndroidRuntime: Shutting down VM 04-19 21:06:10.371 28375-28375/com.example.bledemo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.bledemo, PID: 28375 android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.CALL } at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1801) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1499) at android.app.Activity.startActivityForResult(Activity.java:3942) at android.app.Activity.startActivityForResult(Activity.java:3889) at android.app.Activity.startActivity(Activity.java:4213) at android.app.Activity.startActivity(Activity.java:4181) at com.example.bledemo.DeviceControlActivity$5.onClick(DeviceControlActivity.java:299) at android.view.View.performClick(View.java:5184) at android.view.View$PerformClick.run(View.java:20910) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:5942) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) ```
android 低功耗蓝牙app开发
手机多次跟蓝牙模块连接断开后出现假连接,执行到发现服务并拿到characteristic后就终止了,调用gatt.disconnect()方法,回调onServicesDiscovered()传回的status = 129,还有,感觉多设备连接那一块问题百出,不是连不上就是连上就断,多次断开连接后就开始混乱,哪位高手能详细讲讲ble开发要注意哪些问题?或者分享一些资料
Android BLE开发 连接后获取不到服务
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { List<BluetoothGattService> gattServices = null; if (newState == BluetoothProfile.STATE_CONNECTED) { gattServices = gatt.getServices(); prepareData(gattServices); writeCharacteristicRGB(characteristic, 255, 87, 87, 0); } } }; gatt.getservices 一直为空 是怎么回事啊?是不是没有连接成功?
BLE黑屏后导致APP崩溃
场景1:手机刚刚重启完,运行APP与BLE设备通信,正常无问题(任何情况) 场景2:中断当前BLE操作,退出APP,然后重新与BLE设备通信,一旦把APP切换到后台并黑屏,APP会在几秒内崩溃,logcat没任何错误输出 求大神解答,跪求,以下是捕抓的bug输出(bugly也抓不到),但是重启手机后第一次正常操作,往后就一直会出现描述的问题 04-18 17:58:03.578 2971-3014/? E/BluetoothServiceJni: An exception was thrown by callback 'btgattc_notify_cb'. 04-18 17:58:03.578 2971-3014/? E/BluetoothServiceJni: android.os.DeadObjectException at android.os.BinderProxy.transact(Native Method) at android.bluetooth.IBluetoothGattCallback$Stub$Proxy.onNotify(IBluetoothGattCallback.java:835) at com.android.bluetooth.gatt.GattService.onNotify(GattService.java:724) at dalvik.system.NativeStart.run(Native Method) 04-18 17:58:03.578 2971-3014/? D/BtGatt.btif: btif_gattc_upstreams_evt: Event 10 04-18 17:58:03.578 2971-3014/? E/bt-btif: HAL bt_gatt_callbacks->client->notify_cb 04-18 17:58:03.578 2971-3014/? D/BtGatt.GattService: onNotify() - address=F0:C7:7F:73:68:20, charUuid=0000ffb2-0000-1000-8000-00805f9b34fb, length=19 04-18 17:58:03.578 2971-3014/? E/BluetoothServiceJni: An exception was thrown by callback 'btgattc_notify_cb'. 04-18 17:58:03.578 2971-3014/? E/BluetoothServiceJni: android.os.DeadObjectException at android.os.BinderProxy.transact(Native Method) at android.bluetooth.IBluetoothGattCallback$Stub$Proxy.onNotify(IBluetoothGattCallback.java:835) at com.android.bluetooth.gatt.GattService.onNotify(GattService.java:724) at dalvik.system.NativeStart.run(Native Method) 04-18 17:58:03.578 2971-2982/? D/BtGatt.GattService: Binder is dead - unregistering client (6)! 04-18 17:58:03.578 2971-2982/? D/BtGatt.GattService: stopScan() - queue=0 04-18 17:58:03.578 2971-2982/? D/BtGatt.GattService: stopScan() - queue empty; stopping scan 04-18 17:58:03.578 2971-2982/? D/BtGatt.btif: btif_gattc_scan 04-18 17:58:03.578 2971-2982/? D/BtGatt.GattService: unregisterClient() - clientIf=6 04-18 17:58:03.578 2971-2982/? D/BtGatt.btif: btif_gattc_unregister_app 04-18 17:58:03.578 2971-3014/? D/BtGatt.btif: btgattc_handle_event: Event 1003 04-18 17:58:03.578 2971-3014/? D/BtGatt.btif: btgattc_handle_event: Event 1001 04-18 17:58:03.578 2971-3088/? W/bt-l2cap: L2CA_RemoveFixedChnl() CID: 0x0004 BDA: f0c77f736820 not connected 04-18 17:58:03.578 1156-1539/? D/KeyguardViewMediator: setHidden false 04-18 17:58:03.578 1156-1539/? D/KeyguardUpdateMonitor: sendKeyguardVisibilityChanged(true) 04-18 17:58:03.578 1156-1156/? D/KeyguardUpdateMonitor: handleKeyguardVisibilityChanged(1) 04-18 17:58:03.578 2971-3014/? D/BtGatt.btif: btif_gattc_upstreams_evt: Event 5 04-18 17:58:03.578 2971-3014/? E/bt-btif: HAL bt_gatt_callbacks->client->close_cb 04-18 17:58:03.578 2971-3014/? D/BtGatt.GattService: onDisconnected() - clientIf=6, connId=6, address=F0:C7:7F:73:68:20 04-18 17:58:03.578 2971-3014/? E/BtGatt.ContextMap: Context not found for ID 6
intent.getStringExtra总是返回null
使用android官方低功耗蓝牙demo的时候, intent.getStringExtra总是返回null,求解!! ``` 【DeviceControlActivity】 private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { mConnected = true; updateConnectionState(R.string.connected); invalidateOptionsMenu(); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { mConnected = false; updateConnectionState(R.string.disconnected); invalidateOptionsMenu(); clearUI(); } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { displayGattServices(mBluetoothLeService.getSupportedGattServices()); } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); } } }; ``` ``` 【BluetoothLeService】 private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) { final Intent intent = new Intent(action); if (!UUID_DATA_FROM_ARDUINO.equals(characteristic.getUuid())) { final byte[] data = characteristic.getValue(); if (data != null && data.length > 0) { final StringBuilder stringBuilder = new StringBuilder(data.length); for (byte byteChar : data) stringBuilder.append(String.format("%02X ", byteChar)); intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); } } sendBroadcast(intent); ```
ble 蓝牙在Read方法中读取数据每次只能读取一次,怎么做可以循环读取?
ble蓝牙开发中我们onServicesDiscovered()方法中遍历服务后并且设置数据,然后再onCharacteristicRead()方法中读取数据,然而在读取的方法中每次只能自动读取一次,只有当有数据变化时才会再次读取,但是我想一次读取多个数据,不需要其他的操作,代码怎么实现?下面是我在读取方法中写的,每次只能读取一个数据。求大神帮帮忙? ``` List<BluetoothGattService> services = gatt.getServices(); for (BluetoothGattService s : services) { List<BluetoothGattCharacteristic> gattCharacteristicss = s.getCharacteristics(); for (int i = 0; i < gattCharacteristicss.size(); i++) { BluetoothGattCharacteristic gattCharacteristic = gattCharacteristicss.get(i); Log.e("000", "gattCharacteristicss:" + i + ":" + gattCharacteristic.getUuid().toString()); if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .GAMESIR_BLE_CHARACTERISTICS_X1_Manifacturer)) { try { manifacturer = new String(gattCharacteristic.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.e("000", "Manifacturer:" + manifacturer); } // if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .GAMESIR_BLE_CHARACTERISTICS_X1_Software)) { try { software = new String(gattCharacteristic.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.e("000", "Software:" + software); } else if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .dISHardwareREV_UUID)) { try { hardware = new String(gattCharacteristic.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.e("000", "Hardware:" + hardware); // } else if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .GAMESIR_BLE_CHARACTERISTICS_X1_FIRMWARE)) { try { version = new String(gattCharacteristic.getValue(), "UTF-8"); Log.e("000", "firmware_version数据1:" + version); UpdateUiUtil.setFirmWare(version); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } //////// } else if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .dISSerialNR_UUID)) { try { serial = new String(gattCharacteristic.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.e("000", "Serial:" + serial); } else if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .dISModelNR_UUID)) { try { model = new String(gattCharacteristic.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.e("000", "Model:" + model); // } else if (gattCharacteristic.getUuid().toString().equals(SampleGattAttributes .dISSystemID_UUID)) { try { systemID = new String(gattCharacteristic.getValue(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Log.e("000", "SystemID:" + systemID); } ```
Android打电话出现No Activity found to handle Intent
用了android官方BLE的demo可以成功接收Arduino101板子传入的数据; 在原来的程序中直接加入打电话的代码,可以成功拨打电话 ``` public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gatt_services_characteristics); final Intent intent = getIntent(); mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME); mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS); // Sets up UI references. ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress); mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);//characteristics列表 mGattServicesList.setOnChildClickListener(servicesListClickListner); mConnectionState = (TextView) findViewById(R.id.connection_state); mDataDisplay = (TextView) findViewById(R.id.data_value); getActionBar().setTitle(mDeviceName); getActionBar().setDisplayHomeAsUpEnabled(true); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent callIntent = new Intent(Intent.ACTION_CALL); callIntent.setData(Uri.parse("tel:000000")); } } }); } ``` 但如果改成根据数据的不同,拨打不同电话,就会停止工作,并且报错No Activity found to handle Intent { act=android.intent.action.CALL } ``` public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gatt_services_characteristics); final Intent intent = getIntent(); mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME); mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS); // Sets up UI references. ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress); mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);//characteristics列表 mGattServicesList.setOnChildClickListener(servicesListClickListner); mConnectionState = (TextView) findViewById(R.id.connection_state); mDataDisplay = (TextView) findViewById(R.id.data_value); getActionBar().setTitle(mDeviceName); getActionBar().setDisplayHomeAsUpEnabled(true); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent callIntent = new Intent(Intent.ACTION_CALL); if (number == "00") { callIntent.setData(Uri.parse("tel:000000")); startActivity(callIntent); }else if (number == "01") { callIntent.setData(Uri.parse("tel:000001")); startActivity(callIntent); }else if (number == "02") { callIntent.setData(Uri.parse("tel:000002")); startActivity(callIntent); }else if (number == "03") { callIntent.setData(Uri.parse("tel:000003")); startActivity(callIntent); }else if (number == "04") { callIntent.setData(Uri.parse("tel:000004")); startActivity(callIntent); }else if (number == "05") { callIntent.setData(Uri.parse("tel:000005")); startActivity(callIntent); } } }); } ``` 麻烦各位大神帮忙看一下!!!谢谢!!!
BluetoothGattCallback重复回调
这是概率很低的问题,每次复现这个问题的情况都不太一样,我也还没搞清楚为什么会出现这种问题。 上一次出现这个问题的情况是: 在这次连接之前也有重复连接/断开其他蓝牙设备,最后一次连接蓝牙设备时,蓝牙端显示已连接上,但app端还没收到回调,过了一阵子,onConnectionStateChange才收到回调,接着又自动断开重连,于是,问题就出现了。 当出现这个问题时,BluetoothGattCallback里面的每一个方法断开、连接、发现服务、接收数据等都会重复接收,所以判断是BluetoothGattCallback重复了,但我看了后台服务,确实是只有一个服务; 排除是蓝牙端的问题,因为换蓝牙或者蓝牙关机等都只要APP不重启这个问题依旧在。 所以,应该是还有一个BluetoothGattCallback的对象存在。 那么,有哪些原因可能会导致这种情况呢?如果出现这种情况该怎么解决?比如有没有什么方法可以列出所有的BluetoothGattCallback,然后close其他的BluetoothGattCallback对象,只保留一个? 这是连接部分的代码,这些都是在后台service中执行的 ``` public boolean connect(final String address) { if (mBluetoothAdapter == null) { return false; } if (address == null) { return false; } connectAdress = address; if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt!=null) { if (mBluetoothGatt.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } final BluetoothDevice deivce = mBluetoothAdapter.getRemoteDevice(address); if (deivce == null) { Log.e(TAG, "connect: Device not found. unable to connect." ); return false; } mBluetoothGatt = deivce.connectGatt(this, true, mGattCallback); mBluetoothDeviceAddress = address; mConnectionState = STATE_CONNECTING; return true; } // @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) public void disconnect() { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.e(TAG, "disconnect: BluetoothAdapter not initialized" ); return; } is_click_disconnect = true; VERTICAL_DISCOVER_FLAG = 0; LEVEL_DISCOVER_FLAG = 0; current_connecting_mac_address = ""; mBluetoothGatt.disconnect(); stopSelf(); } ``` 然后这是回调部分的代码, ``` private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { /** * 连接状态改变 * @param gatt * @param status * @param newState */ // @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // super.onConnectionStateChange(gatt, status, newState); String intentAction; if (newState == BluetoothProfile.STATE_CONNECTED) { intentAction = ACTION_GATT_CONNECTED; mConnectionState = STATE_CONNECTED; broadcastUpdate(intentAction); BleMessage message = new BleMessage(); message.setAction(ACTION_GATT_CONNECTED); message.setConnectState(STATE_CONNECTED); // 连接成功 } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STAAE_DISCONNECTED; VERTICAL_DISCOVER_FLAG = 0; LEVEL_DISCOVER_FLAG = 0; Log.e(TAG, "vitec 蓝牙断开连接onConnectionStateChange: Disconnect from gatt server" ); broadcastUpdate(intentAction); textToSpeechHelper.speakChinese("蓝牙连接断开"); //当手动断开连接,关闭mBluetoothGatt if (is_click_disconnect) { mBluetoothGatt.close(); mBluetoothGatt = null; is_click_disconnect = false; } } } /** * 发现服务 * @param gatt * @param status */ @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); enableTXNotification(SYSTEM_RX_SERVICE_UUID, SYSTEM_TX_CHAR_UUID); } /** * 读取特征值 * @param gatt * @param characteristic * @param status */ // @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); Log.e(TAG, "onCharacteristicRead: 当前读取到的特征值为:"+ new String(characteristic.getValue())); } } /** * 写入特征值 * @param gatt * @param characteristic * @param status */ @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); } /** * * @param gatt * @param characteristic */ // @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE,characteristic); } }; ```
安卓蓝牙BLE开发多连接
我现在使用ArrayList集合将得到的gatt放在里面,但是如何进行取出连接及收发的实现
蓝牙Ble通知回调发送命令之后没反应,onCharacteristicChanged
在发送命令之后,onCharacteristicChanged这个回调里面接收不到数据 打开通知 ``` /*打开广播通知*/ private void notifyData() { BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(N_Notify).getCharacteristic(uNotify); BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); bluetoothGatt.writeDescriptor(descriptor); bluetoothGatt.setCharacteristicNotification(characteristic, true); } ``` 发送数据 ``` public void writeData() { if (bluetoothGatt == null) { return; } BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(N_Write).getCharacteristic(uWrite); characteristic.setValue("EF52FFFAFFFF"); bluetoothGatt.writeCharacteristic(characteristic); } ``` 接收通知 ``` @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); bluetoothGatt = gatt; byte[] value = characteristic.getValue(); try { String s=new String(value,"UTF-8"); Log.e(TAG, "onCharacteristicChanged: "+s); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } printNotify(value); } ```
有没有win10 python平台可以查看蓝牙特征值(如电量)的api?
如题,我试过bluepy和pygatt。都只能在linux上用。实在找不到一个可以显示蓝牙电量的api。
C++ windows bluetooth LE 开发
有人用C++ 做windows bluetooth LE 应用开发的吗? 我遇到一个问题:我已经获取了蓝牙设备句柄,获取了服务和特征,设置了通知,并且注册了BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION的回掉函数。虽然现在软件能够和蓝牙设备通信,但是软件运行后开启蓝牙设备,连接或重连接会用较长时间。请问各位大神又没遇到过类似情况呢?
Android的BLE技术中的GattAttributes是干什么的?
最近在研究BLE技术发现了这个东西有一点不明白,有一个GattAttributes的文件 /** * This class includes a small subset of standard GATT attributes for demonstration purposes. */ public class SampleGattAttributes { private static HashMap<String, String> attributes = new HashMap(); public static String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb"; public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; static { // Sample Services. attributes.put("0000180d-0000-1000-8000-00805f9b34fb", "Heart Rate Service"); attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service"); // Sample Characteristics. attributes.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement"); attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String"); } public static String lookup(String uuid, String defaultName) { String name = attributes.get(uuid); return name == null ? defaultName : name; } } 翻译说是一种协议,请问用来干嘛的?
130 个相见恨晚的超实用网站,一次性分享出来
相见恨晚的超实用网站 持续更新中。。。
字节跳动视频编解码面经
三四月份投了字节跳动的实习(图形图像岗位),然后hr打电话过来问了一下会不会opengl,c++,shador,当时只会一点c++,其他两个都不会,也就直接被拒了。 七月初内推了字节跳动的提前批,因为内推没有具体的岗位,hr又打电话问要不要考虑一下图形图像岗,我说实习投过这个岗位不合适,不会opengl和shador,然后hr就说秋招更看重基础。我当时想着能进去就不错了,管他哪个岗呢,就同意了面试...
win10系统安装教程(U盘PE+UEFI安装)
一、准备工作 u盘,电脑一台,win10原版镜像(msdn官网) 二、下载wepe工具箱 极力推荐微pe(微pe官方下载) 下载64位的win10 pe,使用工具箱制作启动U盘打开软件, 选择安装到U盘(按照操作无需更改) 三、重启进入pe系统 1、关机后,将U盘插入电脑 2、按下电源后,按住F12进入启动项选择(技嘉主板是F12) 选择需要启...
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
Python——画一棵漂亮的樱花树(不同种樱花+玫瑰+圣诞树喔)
最近翻到一篇知乎,上面有不少用Python(大多是turtle库)绘制的树图,感觉很漂亮,我整理了一下,挑了一些我觉得不错的代码分享给大家(这些我都测试过,确实可以生成) one 樱花树 动态生成樱花 效果图(这个是动态的): 实现代码 import turtle as T import random import time # 画樱花的躯干(60,t) def Tree(branch, ...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
《奇巧淫技》系列-python!!每天早上八点自动发送天气预报邮件到QQ邮箱
将代码部署服务器,每日早上定时获取到天气数据,并发送到邮箱。 也可以说是一个小人工智障。 思路可以运用在不同地方,主要介绍的是思路。
致 Python 初学者
欢迎来到“Python进阶”专栏!来到这里的每一位同学,应该大致上学习了很多 Python 的基础知识,正在努力成长的过程中。在此期间,一定遇到了很多的困惑,对未来的学习方向感到迷茫。我非常理解你们所面临的处境。我从2007年开始接触 python 这门编程语言,从2009年开始单一使用 python 应对所有的开发工作,直至今天。回顾自己的学习过程,也曾经遇到过无数的困难,也曾经迷茫过、困惑过。开办这个专栏,正是为了帮助像我当年一样困惑的 Python 初学者走出困境、快速成长。希望我的经验能真正帮到你
Java描述设计模式(19):模板方法模式
本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景 通常一款互联网应用的开发流程如下:业务需求,规划产品,程序开发,测试交付。现在基于模板方法模式进行该过程描述。 public class C01_InScene { public static void main(String[] args) { DevelopApp developApp = n...
加快推动区块链技术和产业创新发展,2019可信区块链峰会在京召开
11月8日,由中国信息通信研究院、中国通信标准化协会、中国互联网协会、可信区块链推进计划联合主办,科技行者协办的2019可信区块链峰会将在北京悠唐皇冠假日酒店开幕。   区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。如果说蒸汽机释放了人类的生产力,电力解决了人类基本的生活需求,互联网彻底改变了信息传递的方式,区块链作为构造信任的技术有重要的价值。   1...
C语言魔塔游戏
很早就很想写这个,今天终于写完了。 游戏截图: 编译环境: VS2017 游戏需要一些图片,如果有想要的或者对游戏有什么看法的可以加我的QQ 2985486630 讨论,如果暂时没有回应,可以在博客下方留言,到时候我会看到。 下面我来介绍一下游戏的主要功能和实现方式 首先是玩家的定义,使用结构体,这个名字是可以自己改变的 struct gamerole { char n...
第三个java程序(表白小卡片)
前言: &nbsp;向女神表白啦,作为一个程序员,当然也有爱情啦。只不过,虽然前面两个程序都只是学习了基础的语法结构和向量哈希表。这里涉及的是Swing,awt图形用户界面和一点文件输入输出流的知识。 &nbsp; 表白代码如下: 另附:里面的音乐和图片可以放在一个自己创建的包里面,也可以放在src里面,或者使用绝对路径。至于布局,我自己的使用的是简单的排班,简单的继承。后面的程序会慢慢实现。 ...
8年经验面试官详解 Java 面试秘诀
作者 |胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三百位候选人。在本文里,就将结合本人的面试经验,针对Java初学者、Java初级开发和Java开发,给出若干准备简历和准备面试的建议。 Java程序员准备和投递简历的实...
知乎高赞:中国有什么拿得出手的开源软件产品?(整理自本人原创回答)
知乎高赞:中国有什么拿得出手的开源软件产品? 在知乎上,有个问题问“中国有什么拿得出手的开源软件产品(在 GitHub 等社区受欢迎度较好的)?” 事实上,还不少呢~ 本人于2019.7.6进行了较为全面的回答,对这些受欢迎的 Github 开源项目分类整理如下: 分布式计算、云平台相关工具类 1.SkyWalking,作者吴晟、刘浩杨 等等 仓库地址: apache/skywalking 更...
化繁为简 - 腾讯计费高一致TDXA的实践之路
导语:腾讯计费是孵化于支撑腾讯内部业务千亿级营收的互联网计费平台,在如此庞大的业务体量下,腾讯计费要支撑业务的快速增长,同时还要保证每笔交易不错账。采用最终一致性或离线补...
Linux网络服务-----实验---PXE和Kickstart的无人值守装机
目录 一.PXE的原理 二.kickstart的原理 三.PXE与kickstart的结合使用自动装机 一.PXE的原理 PXE(preboot execute environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服务器下载映像,并由支持通过网络启动操作系统,再启动过程中,终端要求服务器分配IP地址...
究竟你适不适合买Mac?
我清晰的记得,刚买的macbook pro回到家,开机后第一件事情,就是上了淘宝网,花了500元钱,找了一个上门维修电脑的师傅,上门给我装了一个windows系统。。。。。。 表砍我。。。 当时买mac的初衷,只是想要个固态硬盘的笔记本,用来运行一些复杂的扑克软件。而看了当时所有的SSD笔记本后,最终决定,还是买个好(xiong)看(da)的。 已经有好几个朋友问我mba怎么样了,所以今天尽量客观...
A*搜索算法概述
编者按:本文作者奇舞团前端开发工程师魏川凯。A*搜索算法(A-star search algorithm)是一种常见且应用广泛的图搜索和寻径算法。A*搜索算法是通过使用启...
程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
Java工作4年来应聘要16K最后没要,细节如下。。。
前奏: 今天2B哥和大家分享一位前几天面试的一位应聘者,工作4年26岁,统招本科。 以下就是他的简历和面试情况。 基本情况: 专业技能: 1、&nbsp;熟悉Sping了解SpringMVC、SpringBoot、Mybatis等框架、了解SpringCloud微服务 2、&nbsp;熟悉常用项目管理工具:SVN、GIT、MAVEN、Jenkins 3、&nbsp;熟悉Nginx、tomca...
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆每天早上8:30推送 作者|Mr.K 编辑| Emma 来源|技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯...
从顶级黑客到上市公司老板
一看标题,很多老读者就知道我在写什么了。今天Ucloud成功上市,季昕华成为我所熟悉的朋友里又双叒叕一个成功上市的案例。我们认识大概是十五年多吧,如果没记错,第一次见面应该是2004年,...
蓝桥杯知识点汇总:基础知识和常用算法
文章目录基础语法部分:算法竞赛常用API:算法部分数据结构部分 此系列包含蓝桥杯绝大部分所考察的知识点,以及真题题解~ 基础语法部分: 备战蓝桥杯java(一):一般输入输出 和 快速输入输(BufferedReader&amp;BufferedWrite) 备战蓝桥杯java(二):java编程规范和常用数据类型 备战蓝桥杯java(三):常用功能符以及循环结构和分支结构 备战蓝桥杯java(四...
作为一个程序员,CPU的这些硬核知识你必须会!
CPU对每个程序员来说,是个既熟悉又陌生的东西? 如果你只知道CPU是中央处理器的话,那可能对你并没有什么用,那么作为程序员的我们,必须要搞懂的就是CPU这家伙是如何运行的,尤其要搞懂它里面的寄存器是怎么一回事,因为这将让你从底层明白程序的运行机制。 随我一起,来好好认识下CPU这货吧 把CPU掰开来看 对于CPU来说,我们首先就要搞明白它是怎么回事,也就是它的内部构造,当然,CPU那么牛的一个东...
破14亿,Python分析我国存在哪些人口危机!
一、背景 二、爬取数据 三、数据分析 1、总人口 2、男女人口比例 3、人口城镇化 4、人口增长率 5、人口老化(抚养比) 6、各省人口 7、世界人口 四、遇到的问题 遇到的问题 1、数据分页,需要获取从1949-2018年数据,观察到有近20年参数:LAST20,由此推测获取近70年的参数可设置为:LAST70 2、2019年数据没有放上去,可以手动添加上去 3、将数据进行 行列转换 4、列名...
强烈推荐10本程序员在家读的书
很遗憾,这个春节注定是刻骨铭心的,新型冠状病毒让每个人的神经都是紧绷的。那些处在武汉的白衣天使们,尤其值得我们的尊敬。而我们这些窝在家里的程序员,能不外出就不外出,就是对社会做出的最大的贡献。 有些读者私下问我,窝了几天,有点颓丧,能否推荐几本书在家里看看。我花了一天的时间,挑选了 10 本我最喜欢的书,你可以挑选感兴趣的来读一读。读书不仅可以平复恐惧的压力,还可以对未来充满希望,毕竟苦难终将会...
Linux自学篇——linux命令英文全称及解释
man: Manual 意思是手册,可以用这个命令查询其他命令的用法。 pwd:Print working directory 意思是密码。 su:Swith user 切换用户,切换到root用户 cd:Change directory 切换目录 ls:List files 列出目录下的文件 ps:Process Status 进程状态 mkdir:Make directory ...
Python实战:抓肺炎疫情实时数据,画2019-nCoV疫情地图
今天,群里白垩老师问如何用python画武汉肺炎疫情地图。白垩老师是研究海洋生态与地球生物的学者,国家重点实验室成员,于不惑之年学习python,实为我等学习楷模。先前我并没有关注武汉肺炎的具体数据,也没有画过类似的数据分布图。于是就拿了两个小时,专门研究了一下,遂成此文。
疫情数据接口api
返回json示例 { "errcode":0,//0标识接口正常 "data":{ "date":"2020-01-30 07:47:23",//实时更新时间 "diagnosed":7736,//确诊人数 "suspect":12167,//疑是病例人数 "death":170,//死亡人数 "cur...
智力题(程序员面试经典)
NO.1  有20瓶药丸,其中19瓶装有1克/粒的药丸,余下一瓶装有1.1克/粒的药丸。给你一台称重精准的天平,怎么找出比较重的那瓶药丸?天平只能用一次。 解法 有时候,严格的限制条件有可能反倒是解题的线索。在这个问题中,限制条件是天平只能用一次。 因为天平只能用一次,我们也得以知道一个有趣的事实:一次必须同时称很多药丸,其实更准确地说,是必须从19瓶拿出药丸进行称重。否则,如果跳过两瓶或更多瓶药...
相关热词 c# 为空 判断 委托 c#记事本颜色 c# 系统默认声音 js中调用c#方法参数 c#引入dll文件报错 c#根据名称实例化 c#从邮件服务器获取邮件 c# 保存文件夹 c#代码打包引用 c# 压缩效率
立即提问