当前位置:   article > 正文

Android蓝牙功能开发(低功耗与经典)_安卓蓝牙app开发

安卓蓝牙app开发

目录

一、第一种框架集成方式

1.在项目根目录的build.gradle文件中,添加如下配置:

2.在app module的build.gradle中,添加依赖:

3.使用前先在你应用的Application中调init方法初始化框架

4.然后必须调用enableBluetooth()方法开启蓝牙功能,你可以在activity中调用:

5.如果是低功耗蓝牙,需要设置配置项,经典蓝牙忽略跳过这一步即可:

6.开启蓝牙能力后,接着你就可以开始进行蓝牙设备扫描,其中,type 为蓝牙设备类型(经典蓝牙或低功耗蓝牙):

7.一旦扫描到设备,你就可以找到目标设备并连接:

8.设备连接成功后,你可以开始跟设备进行通信:

9.那么如何接收蓝牙设备返回给你的数据呢,很简单,在Receiver中接收:

10.最后,调用以下方法去主动断开连接并释放资源 :

第二种集成方式

1.由于是代码引入,故无需像第一步那样进行库的引入,直接在Application中初始化。

2.蓝牙界面

3.UUidStateBean对象

4.蓝牙信息对象BletoothInfoBen

5.进度对话框

6.ble_servies_select_dialog布局

7.gble_layout蓝牙布局


        Android 蓝牙开发,很多项目会使用到,自己去摸索封装或者引用其他框架,也能解决部分问题。为何说是部分问题,Android蓝牙分为低功耗版与经典版,经典版是可以直接选择即可实现链接,低功耗版是需要配置uuid。故推荐一个框架,下面来分享使用教程。分两部分第一部分是直接使用框架,第二部分是修改框架源码,使用哪一种方式可以结合自己的需要。Android开发建议使用Android蓝牙调试工具app初步调试使用,这里推荐BLE调试助手app,各大应用市场都可以下载。BLE调试助手首页展示。 

Java语言版本地址:https://github.com/g-HJY/HBluetooth
Kotlin语言版本地址:https://github.com/g-HJY/Kotlin-HBluetooth (暂停维护)

一、第一种框架集成方式

         首先是集成方式,当然你可以直接在github上将整个项目下载下来,也可以将其以依赖的形式集成到你的项目中,具体步骤如下:

1.在项目根目录的build.gradle文件中,添加如下配置:

  1. allprojects {
  2. repositories {
  3. ...
  4. maven { url 'https://jitpack.io' }
  5. }
  6. }

2.在app module的build.gradle中,添加依赖:

  1. dependencies {
  2. implementation 'com.github.g-HJY:HBluetooth:V1.3.6'
  3. }

3.使用前先在你应用的Application中调init方法初始化框架

  1. public class XiaoYaApp extends MultiDexApplication {
  2. @Override
  3. public void onCreate() {
  4. super.onCreate();
  5. HBluetooth.init(this);
  6. }
  7. }

4.然后必须调用enableBluetooth()方法开启蓝牙功能,你可以在activity中调用:

  1. //开启蓝牙功能
  2. HBluetooth.getInstance().enableBluetooth()

5.如果是低功耗蓝牙,需要设置配置项,经典蓝牙忽略跳过这一步即可:

        分别是主服务UUID(withServiceUUID)、读写特征值UUID(withWriteCharacteristicUUID)、通知UUID(withNotifyCharacteristicUUID)以及是否设置最大传输单元(setMtu不设置不用调)等; 您还可以设置分包发送的时间间隔和包长度

  1. //请填写你自己设备的UUID
  2. //低功耗蓝牙才需要如下配置BleConfig,经典蓝牙不需要new HBluetooth.BleConfig()
  3. HBluetooth.BleConfig bleConfig = new HBluetooth.BleConfig();
  4. bleConfig.withServiceUUID("0000fe61-0000-1000-8000-00805f9b34fb")
  5. .withWriteCharacteristicUUID("0000fe61-0000-1000-8000-00805f9b34fb")
  6. .withNotifyCharacteristicUUID("0000fe61-0000-1000-8000-00805f9b34fb")
  7. //命令长度大于20个字节时是否分包发送,默认false,分包时可以调两参方法设置包之间发送间隔
  8. //.splitPacketToSendWhenCmdLenBeyond(false)
  9. //useCharacteristicDescriptor 默认false
  10. //.useCharacteristicDescriptor(false)
  11. .setMtu(200, new BleMtuChangedCallback() {
  12. @Override
  13. public void onSetMTUFailure(int realMtuSize, BluetoothException bleException) {
  14. Log.i(TAG, "bleException:" + bleException.getMessage() + " realMtuSize:" + realMtuSize);
  15. }
  16. @Override
  17. public void onMtuChanged(int mtuSize) {
  18. Log.i(TAG, "Mtu set success,mtuSize:" + mtuSize);
  19. }
  20. });
  21. //低功耗蓝牙才需要调setBleConfig
  22. HBluetooth.getInstance().setBleConfig(bleConfig);

6.开启蓝牙能力后,接着你就可以开始进行蓝牙设备扫描,其中,type 为蓝牙设备类型(经典蓝牙或低功耗蓝牙):

  1. HBluetooth.getInstance()
  2. .scan(type, new ScanCallBack() {
  3. @Override
  4. public void onScanStart() {
  5. Log.i(TAG, "开始扫描");
  6. }
  7. @Override
  8. public void onScanning() {
  9. Log.i(TAG, "扫描中");
  10. }
  11. @Override
  12. public void onError(int errorType, String errorMsg) {
  13. }
  14. @Override
  15. public void onScanFinished(List<BluetoothDevice> bluetoothDevices) {
  16. Log.i(TAG, "扫描结束");
  17. if (bluetoothDevices != null && bluetoothDevices.size() > 0) {
  18. list.clear();
  19. list.addAll(bluetoothDevices);
  20. adapter.notifyDataSetChanged();
  21. }
  22. }
  23. });
  24. 或者,如果你想在第一步操作后直接进行扫描,则可以这样调用:
  25. HBluetooth.getInstance()
  26. .enableBluetooth()
  27. .scan(type, new ScanCallBack() {
  28. @Override
  29. public void onScanStart() {
  30. Log.i(TAG, "开始扫描");
  31. }
  32. @Override
  33. public void onScanning() {
  34. Log.i(TAG, "扫描中");
  35. }
  36. @Override
  37. public void onError(int errorType, String errorMsg) {
  38. }
  39. @Override
  40. public void onScanFinished(List<BluetoothDevice> bluetoothDevices) {
  41. Log.i(TAG, "扫描结束");
  42. if (bluetoothDevices != null && bluetoothDevices.size() > 0) {
  43. list.clear();
  44. list.addAll(bluetoothDevices);
  45. adapter.notifyDataSetChanged();
  46. }
  47. }
  48. });

7.一旦扫描到设备,你就可以找到目标设备并连接:

  1. HBluetooth.getInstance()
  2. .connect(device, new ConnectCallBack() {
  3. @Override
  4. public void onConnecting() {
  5. Log.i(TAG, "连接中...");
  6. }
  7. @Override
  8. public void onConnected(Sender sender) {
  9. Log.i(TAG, "连接成功,isConnected:" + mHBluetooth.isConnected());
  10. //调用发送器发送命令
  11. byte[] demoCommand = new byte[]{0x01, 0x02};
  12. sender.send(demoCommand, new SendCallBack() {
  13. @Override
  14. public void onSending(byte[] command) {
  15. Log.i(TAG, "命令发送中...");
  16. }
  17. @Override
  18. public void onSendFailure(BluetoothException bleException) {
  19. Log.e("mylog", "发送命令失败->" + bleException.getMessage());
  20. }
  21. });
  22. }
  23. @Override
  24. public void onDisConnecting() {
  25. Log.i(TAG, "断开连接中...");
  26. }
  27. @Override
  28. public void onDisConnected() {
  29. Log.i(TAG, "已断开连接,isConnected:" + mHBluetooth.isConnected());
  30. }
  31. @Override
  32. public void onError(int errorType, String errorMsg) {
  33. Log.i(TAG, "错误类型:" + errorType + " 错误原因:" + errorMsg);
  34. }
  35. //低功耗蓝牙才需要BleNotifyCallBack
  36. //经典蓝牙可以只调两参方法connect(BluetoothDevice device, ConnectCallBack connectCallBack)
  37. }, new BleNotifyCallBack() {
  38. @Override
  39. public void onNotifySuccess() {
  40. Log.i(TAG, "打开通知成功");
  41. }
  42. @Override
  43. public void onNotifyFailure(BluetoothException bleException) {
  44. Log.i(TAG, "打开通知失败:" + bleException.getMessage());
  45. }
  46. });

8.设备连接成功后,你可以开始跟设备进行通信:

  1. HBluetooth.getInstance()
  2. .send(demoCommand, new SendCallBack() {
  3. @Override
  4. public void onSending(byte[] command) {
  5. Log.i(TAG, "命令发送中...");
  6. }
  7. @Override
  8. public void onSendFailure(BluetoothException bleException) {
  9. Log.e("mylog", "发送命令失败->" + bleException.getMessage());
  10. }
  11. });

9.那么如何接收蓝牙设备返回给你的数据呢,很简单,在Receiver中接收:

  1. public void initListener() {
  2. HBluetooth.getInstance().setReceiver(new ReceiveCallBack() {
  3. @Override
  4. public void onReceived(DataInputStream dataInputStream, byte[] result) {
  5. // 打开通知后,设备发过来的数据将在这里出现
  6. Log.e("mylog", "收到蓝牙设备返回数据->" + Tools.bytesToHexString(result));
  7. }
  8. });
  9. }

10.最后,调用以下方法去主动断开连接并释放资源 :

            HBluetooth.getInstance().release();

其他APi

1.带设备名称过滤条件的扫描:

  1. public void scan(@BluetoothType int scanType, int timeUse, ScanFilter filter, ScanCallBack scanCallBack);
  2. public void scan(@BluetoothType int scanType, ScanFilter filter, ScanCallBack scanCallBack);

2.设置连接超时:

HBluetooth.getInstance().setConnectTimeOut(5000);

3.BleConfig(BLE)设置分包发送时间间隔(默认20ms)及包长度(默认20个字节):

  1. public BleConfig splitPacketToSendWhenCmdLenBeyond(boolean splitPacketToSendWhenCmdLenBeyond, int sendTimeInterval);
  2. public BleConfig splitPacketToSendWhenCmdLenBeyond(boolean splitPacketToSendWhenCmdLenBeyond, int sendTimeInterval, int eachSplitPacketLen);

4.开启断开后自动重连机制,默认关闭重连:

HBluetooth.getInstance().openReconnect(3, 4000);


第二种集成方式

         与第一种区别,第二种是修改第一种源码实现的蓝牙连接,主要是针对低功耗蓝牙适配,第一种是直接在初始化的时候配置uuid,实现要先通过测试工具拿到uuid或者由对方给出uuid,而本demo是通过弹出对话框的方式,由用户去选择,但是也是需要知道对方传递数据的uuid是多少,这就需要用到蓝牙调试助手BLE调试助手。下面是蓝牙调试助手演示界面选择包含读写、通知的uuid去尝试看能否拿到数据,拿到数据的就是低功耗蓝牙的可用uuid。

资源地址:

   https://download.csdn.net/download/shi450561200/88621789

由于模块引入hawk作为已选择的蓝牙数据存储,故还需引入hawk框架。
//hawk数据存储
implementation "com.orhanobut:hawk:2.0.1"

1.由于是代码引入,故无需像第一步那样进行库的引入,直接在Application中初始化。

  1. public class XiaoYaApp extends MultiDexApplication {
  2. @Override
  3. public void onCreate() {
  4. super.onCreate();
  5. //蓝牙
  6. HBluetooth.init(this);//初始化蓝牙
  7. HBluetooth.getInstance()
  8. .setConnectTimeOut(4000);
  9. }
  10. }

2.蓝牙界面

  1. /**
  2. * 经典
  3. * 蓝牙
  4. */
  5. public class GeNBleActivity extends AppCompatActivity implements HandlerUtils.OnReceiveMessageListener {
  6. private RecyclerView recycleview;
  7. private Switch switchBt;
  8. private SwipeRefreshLayout swipeLayout;
  9. private HandlerUtils.HandlerHolder myHandlerUtils;
  10. private int clickState = 1999;//防止误碰蓝牙连接
  11. private TextView blueTxt;//蓝牙数据显示
  12. private LinearLayout finish;
  13. private String tys = "";//
  14. @Override
  15. protected void onCreate(@Nullable Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.gble_layout);
  18. FullScreenrUtils.initBar(this);//全屏
  19. StatusBarUtils.setLightStatusBar(this, true);//设置状态栏黑色字体
  20. // new Thread(new Runnable() {
  21. // @Override
  22. // public void run() {
  23. // registerCustomBroadcastReceiver();
  24. // }
  25. // }).start();
  26. tys = getIntent().getExtras().get("typs").toString();
  27. initView();
  28. }
  29. /**
  30. * 刷新
  31. * 数据
  32. */
  33. private int refreshCount = 0;
  34. private void refreshView() {
  35. swipeLayout.setColorSchemeColors(ContextCompat.getColor(this, R.color.colorPrimary));
  36. swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  37. @Override
  38. public void onRefresh() {
  39. clickState = 0;
  40. //开关试图打开
  41. switchBt.setSwitchPadding(2);
  42. switchBt.setChecked(true);
  43. //开关试图打开
  44. if (refreshCount > 0) {
  45. //搜索蓝牙子线程中执行
  46. new Thread(new Runnable() {
  47. @Override
  48. public void run() {
  49. HBluetooth.getInstance().release();
  50. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  51. initData();
  52. }
  53. }).start();
  54. } else {
  55. switchBt.setSwitchPadding(2);
  56. switchBt.setChecked(true);
  57. }
  58. //1.5s后关掉下拉刷新
  59. swipeLayout.postDelayed(new Runnable() {
  60. @Override
  61. public void run() {
  62. swipeLayout.setRefreshing(false);
  63. refreshCount = refreshCount + 1;
  64. }
  65. }, 2000);
  66. }
  67. });
  68. }
  69. /**
  70. * 初始化
  71. * 数据
  72. */
  73. private static final int REQUEST_ENABLE_BT = 0xff000099;//启用蓝牙请求码
  74. @SuppressLint("WrongConstant")
  75. private void initData() {
  76. int type = 2;
  77. // 或者,如果你想在第一步操作后直接进行扫描,则可以这样调用:
  78. HBluetooth.getInstance()
  79. .enableBluetooth()
  80. .scan(type, 3000, new ScanCallBack() {
  81. @Override
  82. public void onScanStart() {
  83. // Log.i(TAG, "==开始扫描==");
  84. }
  85. @Override
  86. public void onScanning(List<BluetoothDevice> scannedDevices, BluetoothDevice currentScannedDevice) {
  87. // Log.i(TAG, "==扫描中==");
  88. if (scannedDevices != null && scannedDevices.size() > 0) {
  89. list.clear();
  90. list.addAll(scannedDevices);
  91. runOnUiThread(new Runnable() {
  92. @Override
  93. public void run() {
  94. bluetoothDevicesAdapter.notifyDataSetChanged();
  95. }
  96. });
  97. }
  98. }
  99. @Override
  100. public void onError(int errorType, String errorMsg) {
  101. // Log.d(TAG, "onError");
  102. }
  103. @Override
  104. public void onScanFinished(List<BluetoothDevice> bluetoothDevices) {
  105. // Log.d(TAG, "==onScanFinished===");
  106. if (bluetoothDevices != null && bluetoothDevices.size() > 0) {
  107. list.clear();
  108. list.addAll(bluetoothDevices);
  109. runOnUiThread(new Runnable() {
  110. @Override
  111. public void run() {
  112. bluetoothDevicesAdapter.notifyDataSetChanged();
  113. }
  114. });
  115. }
  116. }
  117. });
  118. }
  119. //蓝牙设备适配器
  120. private MyDemoBluetoothDevicesAdapter bluetoothDevicesAdapter;
  121. private List<BluetoothDevice> list = new ArrayList<>();
  122. private static final String TAG = "TAG";
  123. private String bleDevicesAdress = "";
  124. private void initView() {
  125. XiaoYaApp.setUuidTmp("");
  126. // XiaoYaApp.setUuidTmp("0000ffe0-0000-1000-8000-00805f9b34fb");
  127. finish = findViewById(R.id.finish);
  128. recycleview = findViewById(R.id.recycleview);
  129. switchBt = findViewById(R.id.switch_bt);
  130. swipeLayout = findViewById(R.id.swipeLayout);
  131. blueTxt = findViewById(R.id.blue_txt);
  132. LinearLayoutManager linearLayoutManager = new LinearLayoutManager(GeNBleActivity.this);
  133. linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
  134. recycleview.setLayoutManager(linearLayoutManager);
  135. recycleview.setHasFixedSize(true);
  136. bluetoothDevicesAdapter = new MyDemoBluetoothDevicesAdapter(GeNBleActivity.this, list);
  137. recycleview.setAdapter(bluetoothDevicesAdapter);
  138. myHandlerUtils = new HandlerUtils.HandlerHolder(GeNBleActivity.this);
  139. bluetoothDevicesAdapter.setMyOnItemClickListener(new MyDemoBluetoothDevicesAdapter.OnItemClickListener() {
  140. @Override
  141. public void OnItemClick(View view, int position) {
  142. if (view.getId() == R.id.tv_cancle_conn) {
  143. new Thread(new Runnable() {
  144. @Override
  145. public void run() {
  146. HBluetooth.getInstance().release();
  147. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  148. }
  149. }).start();
  150. } else {
  151. if (clickState == 1999) {
  152. return;
  153. }
  154. clickState = 1999;
  155. myListPosition = position;
  156. try {
  157. //4、连接
  158. // Log.e(getPackageName(), "===开始连接=Exception===");
  159. // Log.e(TAG, "==扫描uuid==" + Arrays.toString(list.get(position).getUuids()));
  160. //保存蓝牙Address数据,供直连使用。
  161. bleDevicesAdress = list.get(position).getAddress();
  162. new Thread(new Runnable() {
  163. @Override
  164. public void run() {
  165. HBluetooth.getInstance().release();
  166. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  167. initListener();
  168. connectData(list.get(position));
  169. }
  170. }).start();
  171. } catch (Exception e) {
  172. }
  173. }
  174. }
  175. @Override
  176. public void OnItemLonClick(int position) {
  177. }
  178. });
  179. //选择
  180. switchBt.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
  181. @Override
  182. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  183. if (!getPermission()) {
  184. return;
  185. }
  186. if (isChecked) {
  187. //打开蓝牙
  188. switchBt.setSwitchPadding(2);
  189. //扫描蓝牙
  190. new Thread(new Runnable() {
  191. @Override
  192. public void run() {
  193. HBluetooth.getInstance().release();
  194. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  195. initData();
  196. }
  197. }).start();
  198. } else {
  199. //关闭蓝牙
  200. switchBt.setSwitchPadding(1);
  201. //关闭蓝牙
  202. new Thread(new Runnable() {
  203. @Override
  204. public void run() {
  205. HBluetooth.getInstance().release();
  206. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  207. }
  208. }).start();
  209. list.clear();
  210. bluetoothDevicesAdapter.notifyDataSetChanged();
  211. }
  212. }
  213. });
  214. clickState = 0;
  215. refreshView();
  216. //一进入页面就取一次缓存
  217. // MyEventManager.postMsg("=getcahegetcahe=", "getCache");
  218. getCacheData();
  219. finish.setOnClickListener(new View.OnClickListener() {
  220. @Override
  221. public void onClick(View v) {
  222. finish();
  223. }
  224. });
  225. //打开蓝牙搜索
  226. switchBt.setSwitchPadding(2);
  227. switchBt.setChecked(true);
  228. }
  229. /**
  230. * 修改
  231. * 蓝牙数据
  232. */
  233. private int myListPosition = 0;
  234. private void upBlutoothSata(boolean isConnnted) {
  235. if (isConnnted) {
  236. XiaoYaApp.getBlDevices().setType(999);
  237. // Toast.makeText(GeNBleActivity.this, "蓝牙连接成功", Toast.LENGTH_SHORT).show();
  238. } else {
  239. XiaoYaApp.getBlDevices().setType(333);
  240. // Toast.makeText(GeNBleActivity.this, "蓝牙已断开", Toast.LENGTH_SHORT).show();
  241. }
  242. runOnUiThread(new Runnable() {
  243. @Override
  244. public void run() {
  245. // bluetoothDevicesAdapter.notifyItemChanged(myListPosition, XiaoYaApp.getBlDevices());
  246. bluetoothDevicesAdapter.notifyDataSetChanged();
  247. // MyEventManager.postMsg("==更新页面状态==" + XiaoYaApp.getBlDevices().getType(), "formAndroid");
  248. myHandlerUtils.sendEmptyMessageDelayed(UPDATE_DEVICESTYPE, 100);
  249. // XiaoYaApp.getBlDevices().setType(2);
  250. }
  251. });
  252. }
  253. /**
  254. * 连接
  255. * 蓝牙
  256. */
  257. private void connectData(BluetoothDevice device) {
  258. runOnUiThread(new Runnable() {
  259. @Override
  260. public void run() {
  261. showProgressDialog();
  262. }
  263. });
  264. //保存蓝牙信息
  265. Logger.d("===开始连接--====" + (device != null));
  266. isConneted = false;//蓝牙能否重连,false表示不重连
  267. // Log.d(TAG, "===connectData:开始 000===");
  268. if (device != null) {
  269. XiaoYaApp.setBlDevices(device);//保存全局的device
  270. } else {
  271. cancleDialogProgress();
  272. return;
  273. }
  274. // Log.d(TAG, "===connectData:开始 1111===");
  275. HBluetooth.getInstance()
  276. .setConnectTimeOut(4000)
  277. .connect(device, new ConnectCallBack() {
  278. @Override
  279. public void onConnecting() {
  280. Logger.d("=====连接中=====");
  281. }
  282. @Override
  283. public void onConnected(Sender sender) {
  284. clickState = 0;
  285. Logger.d("=====连接成功=====");
  286. myHandlerUtils.sendEmptyMessageDelayed(TIPS_SELECT_UUID, 3000);
  287. //调用发送器发送命令
  288. byte[] demoCommand = new byte[]{0x01, 0x02};
  289. sender.send(demoCommand, new SendCallBack() {
  290. @Override
  291. public void onSending(byte[] command) {
  292. // Log.i(TAG, "==命令发送中..==");
  293. }
  294. @Override
  295. public void onSendFailure(BluetoothException bleException) {
  296. // Log.d(TAG, "==发送命令失败->===" + bleException.getMessage());
  297. }
  298. });
  299. }
  300. @Override
  301. public void onDisConnecting() {
  302. // Log.d(TAG, "===断开连接中...===");
  303. }
  304. @Override
  305. public void onDisConnected() {
  306. clickState = 0;
  307. Logger.d("=====已断开连接=====");
  308. myHandlerUtils.sendEmptyMessage(UPDATE_BLT_DISC_STATE);//修改蓝牙为断开状态
  309. // Log.d(TAG, "===断开...===");
  310. cancleDialogProgress();
  311. }
  312. @Override
  313. public void onError(int errorType, String errorMsg) {
  314. // Log.d(TAG, "==错误类型:" + errorType + " ===错误原因:" + errorMsg);
  315. }
  316. //低功耗蓝牙才需要BleNotifyCallBack
  317. //经典蓝牙可以只调两参方法connect(BluetoothDevice device, ConnectCallBack connectCallBack)
  318. }, new BleNotifyCallBack() {
  319. @Override
  320. public void onNotifySuccess() {
  321. isConneted = true;
  322. myHandlerUtils.sendEmptyMessageDelayed(UPDATE_BLT_CONNTED_STATE, 3000);//修改蓝牙显示连接状态
  323. cancleDialogProgress();
  324. // senDMsgDataDe();
  325. Logger.d("===打开通知成功--====");
  326. }
  327. @Override
  328. public void onNotifyFailure(BluetoothException bleException) {
  329. cancleDialogProgress();
  330. Logger.d("===打开通知失败--====");
  331. }
  332. });
  333. }
  334. /**
  335. * 接收
  336. * 数据
  337. * 监听
  338. */
  339. public void initListener() {
  340. HBluetooth.getInstance().setReceiver(new ReceiveCallBack() {
  341. @Override
  342. public void onReceived(DataInputStream dataInputStream, byte[] result) {
  343. Logger.d("===接收数据====" + Tools.bytesToHexString(result));
  344. // 打开通知后,设备发过来的数据将在这里出现
  345. }
  346. });
  347. HBluetooth.getInstance().openReconnect(200, 4000);
  348. }
  349. /**
  350. * Create a
  351. * BroadcastReceiver
  352. * for ACTION_FOUND.
  353. * 扫描发现设备
  354. * 蓝牙配对并连接
  355. */
  356. @Override
  357. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  358. super.onActivityResult(requestCode, resultCode, data);
  359. if (requestCode == REQUEST_ENABLE_BT) {//打开蓝牙回调
  360. if (resultCode == RESULT_OK) {
  361. // Log.d("TAG", "====onActivityResult:成功======");
  362. }
  363. }
  364. }
  365. @Override
  366. protected void onResume() {
  367. super.onResume();
  368. }
  369. @Override
  370. protected void onStop() {
  371. super.onStop();
  372. }
  373. @Override
  374. protected void onDestroy() {
  375. super.onDestroy();
  376. HBluetooth.getInstance().release();
  377. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  378. }
  379. /**
  380. * 重连
  381. * 监听
  382. */
  383. private static final int UPDATE_BLT_CONNTED_STATE = 0x000666;
  384. private static final int UPDATE_BLT_DISC_STATE = 0x0000777;
  385. private static final int TIPS_SELECT_UUID = 0x000888;//提示选择服务id
  386. private static final int UPDATE_DEVICESTYPE = 1000;
  387. private static final int SELECT_CONN = 0X0001;
  388. private boolean isConneted = false;
  389. @Override
  390. public void handlerMessage(Message msg) {
  391. switch (msg.what) {
  392. case UPDATE_BLT_CONNTED_STATE://修改蓝牙为连接待接收数据状态
  393. isConneted = true;
  394. new Thread(new Runnable() {
  395. @Override
  396. public void run() {
  397. upBlutoothSata(true);
  398. }
  399. }).start();
  400. break;
  401. case UPDATE_BLT_DISC_STATE://修改蓝牙为断开状态
  402. new Thread(new Runnable() {
  403. @Override
  404. public void run() {
  405. upBlutoothSata(false);
  406. }
  407. }).start();
  408. break;
  409. case TIPS_SELECT_UUID:
  410. // Log.d(TAG, "===延时2S显示配置服务UUID: ==" + isConneted);
  411. showServicesUUid();//延时2S显示配置服务UUID
  412. break;
  413. case UPDATE_DEVICESTYPE://修 XiaoYaApp.getBlDevices().setType(2);
  414. new Thread(new Runnable() {
  415. @Override
  416. public void run() {
  417. XiaoYaApp.getBlDevices().setType(2);
  418. }
  419. }).start();
  420. break;
  421. case SELECT_CONN:
  422. oneConnectBle();//选择服务连接
  423. break;
  424. default:
  425. break;
  426. }
  427. }
  428. /**
  429. * 只连接
  430. * 蓝牙一次
  431. */
  432. private void oneConnectBle() {
  433. BluetoothDevice bluetoothDevice = XiaoYaApp.getBlDevices();
  434. new Thread(new Runnable() {
  435. @Override
  436. public void run() {
  437. Logger.d("===连接蓝牙====");
  438. // Log.d(TAG, "====handleMessage:==只连接蓝牙一次===");
  439. if (bluetoothDevice != null) {
  440. // HBluetooth.getInstance().release();
  441. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  442. XiaoYaApp.getBlDevices().setType(2);
  443. connectData(bluetoothDevice);
  444. }
  445. }
  446. }).start();
  447. }
  448. /**
  449. * 判断权限
  450. * 是否通过,
  451. * 如果通过
  452. * 就初始化
  453. */
  454. private boolean mHasPermission; // 是否通过权限
  455. private boolean getPermission() {
  456. mHasPermission = checkPermission();
  457. if (!mHasPermission) {
  458. // 未获取权限,申请权限
  459. runOnUiThread(new Runnable() {
  460. @Override
  461. public void run() {
  462. Toast.makeText(GeNBleActivity.this, "未获取权限,申请权限", Toast.LENGTH_SHORT).show();
  463. }
  464. });
  465. requestPermission();
  466. } else if (mHasPermission) {
  467. // 已经获取权限
  468. runOnUiThread(new Runnable() {
  469. @Override
  470. public void run() {
  471. Toast.makeText(GeNBleActivity.this, "已经获取权限", Toast.LENGTH_SHORT).show();
  472. }
  473. });
  474. }
  475. return mHasPermission;
  476. }
  477. /**
  478. * 显示UUID
  479. */
  480. private void showServicesUUid() {
  481. mServiceList = new ArrayList<>();
  482. uUidStateBeanList = new ArrayList<>();
  483. mServiceList.clear();
  484. uUidStateBeanList.clear();
  485. mServiceList = XiaoYaApp.getmServiceList();
  486. Log.d(TAG, "==showServicesUUid: =mServiceList集合大小==" + (mServiceList == null));
  487. for (int y = 0; y < mServiceList.size(); y++) {
  488. UUidStateBean uu = new UUidStateBean();
  489. uu.setUUid(mServiceList.get(y).getUuid() + "");
  490. uu.setSelected(false);
  491. uUidStateBeanList.add(uu);
  492. }
  493. // Log.d(TAG, "===showServicesUUid:取消对话框======");
  494. cancleDialogProgress();
  495. if (!isConneted && mServiceList != null) {
  496. showDialog();
  497. // Toast.makeText(GeNBleActivity.this, "数据", Toast.LENGTH_LONG).show();
  498. } else {
  499. BluetoothDevice blethDeviceInfo = XiaoYaApp.getBlDevices();
  500. saveBleDevicesInfo(blethDeviceInfo.getName(), blethDeviceInfo.getAddress(), "");
  501. }
  502. }
  503. /**
  504. * 显示UUId
  505. * 供用户
  506. * 选择
  507. */
  508. private RecyclerView dialogServList;
  509. private BtUUIDSelectAdapter btUUIDSelectAdapter;
  510. private List<BluetoothGattService> mServiceList;
  511. private List<UUidStateBean> uUidStateBeanList;
  512. private int selectUUidPosition = 0;
  513. private void showDialog() {
  514. View view = getLayoutInflater().from(this).inflate(R.layout.ble_servies_select_dialog, null);
  515. dialogServList = view.findViewById(R.id.dialogServList);
  516. btUUIDSelectAdapter = new BtUUIDSelectAdapter(GeNBleActivity.this, uUidStateBeanList);
  517. LinearLayoutManager linearLayoutManager = new LinearLayoutManager(GeNBleActivity.this);
  518. linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
  519. dialogServList.setLayoutManager(linearLayoutManager);
  520. dialogServList.setHasFixedSize(true);
  521. dialogServList.setAdapter(btUUIDSelectAdapter);
  522. final AlertDialog dialog = new AlertDialog.Builder(this).create();
  523. dialog.setCancelable(true);
  524. dialog.setCanceledOnTouchOutside(false);
  525. TextView tv_cancle = view.findViewById(R.id.common_dialog_cancel_tv);
  526. tv_cancle.setText("取消");
  527. TextView tv_sure = view.findViewById(R.id.common_dialog_confirm_tv);
  528. tv_sure.setText("确定");
  529. tv_sure.setTextColor(Color.parseColor("#ff333333"));
  530. TextView tv_title = view.findViewById(R.id.common_dialog_title_tv);
  531. tv_title.setText("请选择可用UUID");
  532. //确定
  533. tv_sure.setOnClickListener(new View.OnClickListener() {
  534. @Override
  535. public void onClick(View view) {
  536. BluetoothDevice blethDevice = XiaoYaApp.getBlDevices();
  537. new Thread(new Runnable() {
  538. @Override
  539. public void run() {
  540. HBluetooth.getInstance().release();
  541. // HBluetooth.getInstance().openReconnect(0, 0);//关闭重连
  542. String uuidServices = uUidStateBeanList.get(selectUUidPosition).getUUid() + "" + XiaoYaApp.getUuidTmp();
  543. XiaoYaApp.setUuidTmp(uuidServices + "");
  544. //取缓存
  545. myHandlerUtils.sendEmptyMessageDelayed(SELECT_CONN, 200);
  546. myHandlerUtils.sendEmptyMessageDelayed(UPDATE_BLT_CONNTED_STATE, 1000);
  547. //保存蓝牙信息
  548. saveBleDevicesInfo(blethDevice.getName(), blethDevice.getAddress(), uuidServices);
  549. dialog.dismiss();
  550. }
  551. }).start();
  552. }
  553. });
  554. //取消对话框
  555. tv_cancle.setOnClickListener(new View.OnClickListener() {
  556. @Override
  557. public void onClick(View v) {
  558. dialog.dismiss();
  559. }
  560. });
  561. dialog.show();
  562. dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
  563. //设置位置窗体
  564. Window window = dialog.getWindow();
  565. window.setGravity(Gravity.CENTER);
  566. // WindowManager.LayoutParams lp = window.getAttributes();
  567. // lp.dimAmount =0.0f;
  568. // lp.x = 0; //新位置X坐标
  569. // lp.y = -400; //新位置Y坐标
  570. // dialog.onWindowAttributesChanged(lp);
  571. window.setContentView(view);
  572. dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);//弹框
  573. dialog.getWindow().setLayout((this.getWindowManager().getDefaultDisplay().getWidth() / 5 * 3), LinearLayout.LayoutParams.WRAP_CONTENT);
  574. dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
  575. btUUIDSelectAdapter.notifyDataSetChanged();
  576. btUUIDSelectAdapter.setMyOnItemClickListener(new BtUUIDSelectAdapter.OnItemClickListener() {
  577. @Override
  578. public void OnItemClick(View view, int position) {
  579. selectUUidPosition = position;
  580. for (int y = 0; y < uUidStateBeanList.size(); y++) {
  581. uUidStateBeanList.get(y).setSelected(false);
  582. }
  583. UUidStateBean uUidStateBean = new UUidStateBean();
  584. uUidStateBean.setSelected(true);
  585. uUidStateBean.setUUid(uUidStateBeanList.get(position).getUUid() + "");
  586. uUidStateBeanList.set(position, uUidStateBean);
  587. btUUIDSelectAdapter.notifyDataSetChanged();
  588. }
  589. @Override
  590. public void OnItemLonClick(int position) {
  591. }
  592. });
  593. }
  594. /**
  595. * 发送
  596. * 数据
  597. */
  598. public void senDMsgDataDe() {
  599. // MyEventManager.postMsg("==拉取数据请求==" + strHex, "formAndroid");
  600. byte[] demoCommand = BlueToothUtils.hex2Byte("ff fe 0b 27 01 d0 00 17 04 03 0f 1e 00");
  601. // byte[] demoCommand = BlueToothUtils.hex2Byte(strHex);
  602. int s = 0;
  603. while (true) {
  604. s++;
  605. if (s > 2) {
  606. break;
  607. }
  608. try {
  609. Thread.sleep(1500);
  610. HBluetooth.getInstance()
  611. .send(demoCommand, new SendCallBack() {
  612. @Override
  613. public void onSending(byte[] command) {
  614. // Log.d(TAG, "命令发送中123...");
  615. }
  616. @Override
  617. public void onSendFailure(BluetoothException bleException) {
  618. // Log.d(TAG, "发送命令失败->" + bleException.getMessage());
  619. }
  620. });
  621. } catch (InterruptedException e) {
  622. e.printStackTrace();
  623. }
  624. }
  625. }
  626. /**
  627. * 申请
  628. * 权限
  629. */
  630. private void requestPermission() {
  631. ActivityCompat.requestPermissions(this, NEEDED_PERMISSIONS, PERMISSION_REQUEST_CODE);
  632. }
  633. /**
  634. * @return 检查
  635. * 是否
  636. * 已经
  637. * 授予权限
  638. */
  639. private boolean checkPermission() {
  640. for (String permission : NEEDED_PERMISSIONS) {
  641. if (ActivityCompat.checkSelfPermission(this, permission)
  642. != PackageManager.PERMISSION_GRANTED) {
  643. return false;
  644. }
  645. }
  646. return true;
  647. }
  648. private static final int PERMISSION_REQUEST_CODE = 0;
  649. // 两个权限需要动态申请
  650. private static final String[] NEEDED_PERMISSIONS = new String[]{
  651. Manifest.permission.ACCESS_COARSE_LOCATION,
  652. Manifest.permission.ACCESS_FINE_LOCATION,
  653. Manifest.permission.READ_EXTERNAL_STORAGE,
  654. Manifest.permission.WRITE_EXTERNAL_STORAGE,
  655. };
  656. /**
  657. * 监听从uni-app
  658. * 传过来的蓝牙uuid
  659. * 缓存数据
  660. */
  661. private String cacheServicesId = "";
  662. private List<BletoothInfoBen> blueListInfo;//蓝牙设备信息
  663. private void getCacheData() {
  664. blueListInfo = new ArrayList<>();
  665. String tp = tys;//页面跳转的时候传过来
  666. String value = Hawk.get(tp);//取低功耗蓝牙数据
  667. Gson gson = new Gson();
  668. Type type = new TypeToken<ArrayList<BletoothInfoBen>>() {
  669. }.getType();
  670. blueListInfo = gson.fromJson(value, type);
  671. StringBuilder stb = new StringBuilder();
  672. if (blueListInfo==null){
  673. return;
  674. }
  675. // 拿到蓝牙yaservicesID
  676. if (blueListInfo.size() > 0) {
  677. for (int y = 0; y < blueListInfo.size(); y++) {
  678. stb.append(blueListInfo.get(y).getServicesId() + " ");
  679. }
  680. }
  681. XiaoYaApp.setUuidTmp(stb + ",");
  682. Logger.d("=====获取到缓存蓝牙数据======" + stb);
  683. }
  684. /**
  685. * 保存
  686. * 蓝牙设备
  687. * 信息数据
  688. */
  689. private void saveBleDevicesInfo(String name, String devicesAdress, String servicesId) {
  690. long str = System.currentTimeMillis();
  691. String tp = tys;//页面跳转的时候传过来
  692. String names = "";
  693. if (name != null) {
  694. names = name;
  695. }
  696. String times = MyDateUtils.getSimpleYMDDate(str);
  697. BletoothInfoBen bluetoothDevice = new BletoothInfoBen();
  698. bluetoothDevice.setName(names);
  699. bluetoothDevice.setTypes(tp);
  700. bluetoothDevice.setDeviceId(devicesAdress);
  701. bluetoothDevice.setServicesId(servicesId);
  702. bluetoothDevice.setBindTime(times);
  703. if (blueListInfo==null){
  704. return;
  705. }
  706. blueListInfo.add(bluetoothDevice);
  707. String result = JSON.toJSONString(blueListInfo);
  708. Hawk.put(tp, result);//保存低功耗蓝牙
  709. }
  710. /**
  711. * 关闭对话框
  712. */
  713. private void cancleDialogProgress() {
  714. if (dialogProgress != null) {
  715. runOnUiThread(new Runnable() {
  716. @Override
  717. public void run() {
  718. dialogProgress.cancel();
  719. }
  720. });
  721. }
  722. }
  723. /**
  724. * 进度对话框
  725. */
  726. private AlertDialog dialogProgress;
  727. private void showProgressDialog() {
  728. View view = getLayoutInflater().from(this).inflate(R.layout.ble_dialog_progress_layout, null);
  729. LinearLayoutManager linearLayoutManager = new LinearLayoutManager(GeNBleActivity.this);
  730. linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
  731. // TextView progress_dialog_title = view.findViewById(R.id.progress_dialog_title);
  732. // progress_dialog_title.setText("启动蓝牙连接");
  733. dialogProgress = new AlertDialog.Builder(this).create();
  734. dialogProgress.setCancelable(true);
  735. dialogProgress.setCanceledOnTouchOutside(true);
  736. dialogProgress.show();
  737. dialogProgress.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
  738. //设置位置窗体
  739. Window window = dialogProgress.getWindow();
  740. window.setGravity(Gravity.CENTER);
  741. window.setContentView(view);
  742. dialogProgress.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);//弹框
  743. dialogProgress.getWindow().setLayout((this.getWindowManager().getDefaultDisplay().getWidth() / 5 * 3), LinearLayout.LayoutParams.WRAP_CONTENT);
  744. dialogProgress.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
  745. }
  746. }

3.UUidStateBean对象

  1. public class UUidStateBean {
  2. private int state;
  3. private String UUid;
  4. private boolean selected;
  5. public int getState() {
  6. return state;
  7. }
  8. public void setState(int state) {
  9. this.state = state;
  10. }
  11. public String getUUid() {
  12. return UUid;
  13. }
  14. public void setUUid(String UUid) {
  15. this.UUid = UUid;
  16. }
  17. public boolean isSelected() {
  18. return selected;
  19. }
  20. public void setSelected(boolean selected) {
  21. this.selected = selected;
  22. }
  23. @Override
  24. public String toString() {
  25. return "UUidStateBean{" +
  26. "state=" + state +
  27. ", UUid='" + UUid + '\'' +
  28. ", selected=" + selected +
  29. '}';
  30. }
  31. }

4.蓝牙信息对象BletoothInfoBen

  1. /**
  2. * 蓝牙
  3. * 信息对象
  4. */
  5. public class BletoothInfoBen implements Serializable {
  6. private String name;//蓝牙名称
  7. private String types;//蓝牙类型 体温计or 血糖仪等等
  8. private String deviceId;//蓝牙设备id
  9. private String servicesId;//蓝牙服务id
  10. private String bindTime;//绑定时间
  11. public BletoothInfoBen() {
  12. }
  13. public BletoothInfoBen(String name, String types, String deviceId, String servicesId, String bindTime) {
  14. this.types = types;
  15. this.name = name;
  16. this.deviceId = deviceId;
  17. this.servicesId = servicesId;
  18. this.bindTime = bindTime;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public String getTypes() {
  27. return types;
  28. }
  29. public void setTypes(String types) {
  30. this.types = types;
  31. }
  32. public String getDeviceId() {
  33. return deviceId;
  34. }
  35. public void setDeviceId(String deviceId) {
  36. this.deviceId = deviceId;
  37. }
  38. public String getServicesId() {
  39. return servicesId;
  40. }
  41. public void setServicesId(String servicesId) {
  42. this.servicesId = servicesId;
  43. }
  44. public String getBindTime() {
  45. return bindTime;
  46. }
  47. public void setBindTime(String bindTime) {
  48. this.bindTime = bindTime;
  49. }
  50. @Override
  51. public String toString() {
  52. return "BletoothInfoBen{" +
  53. "name='" + name + '\'' +
  54. ", deviceId='" + deviceId + '\'' +
  55. ", servicesId='" + servicesId + '\'' +
  56. ", bindTime='" + bindTime + '\'' +
  57. '}';
  58. }
  59. }

5.进度对话框

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="@dimen/dp_160"
  6. android:background="@drawable/popup_dialog_bg"
  7. android:gravity="center"
  8. android:orientation="vertical">
  9. <TextView
  10. android:id="@+id/enter_wifi_password"
  11. android:layout_width="match_parent"
  12. android:layout_height="@dimen/dp_50"
  13. android:layout_marginLeft="@dimen/dp_35"
  14. android:layout_marginRight="@dimen/dp_35"
  15. android:background="@null"
  16. android:gravity="center"
  17. android:text="蓝牙连接中......"
  18. android:textAlignment="center"
  19. android:textColor="#333333"
  20. android:textSize="@dimen/sp_14" />
  21. </LinearLayout>

6.ble_servies_select_dialog布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:background="@drawable/popup_dialog_bg"
  7. android:orientation="vertical">
  8. <RelativeLayout
  9. android:id="@+id/common_dialog_top_rl"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. android:layout_marginBottom="@dimen/dp_10"
  13. android:gravity="center_vertical"
  14. android:paddingLeft="15dp"
  15. android:paddingRight="15dp">
  16. <TextView
  17. android:id="@+id/common_dialog_title_tv"
  18. android:layout_width="match_parent"
  19. android:layout_height="wrap_content"
  20. android:layout_marginTop="@dimen/dp_15"
  21. android:gravity="center_horizontal"
  22. android:textColor="#555555"
  23. android:textSize="@dimen/sp_16"
  24. tools:text="标题" />
  25. </RelativeLayout>
  26. <androidx.recyclerview.widget.RecyclerView
  27. android:id="@+id/dialogServList"
  28. android:layout_width="match_parent"
  29. android:layout_height="match_parent"
  30. android:layout_marginTop="5dp"
  31. android:layout_weight="1" />
  32. <View
  33. android:layout_width="match_parent"
  34. android:layout_height="0.5dp"
  35. android:background="#F5F5F5" />
  36. <LinearLayout
  37. android:id="@+id/common_dialog_bottom_ll"
  38. android:layout_width="match_parent"
  39. android:layout_height="45dp"
  40. android:orientation="horizontal">
  41. <TextView
  42. android:id="@+id/common_dialog_cancel_tv"
  43. android:layout_width="0dp"
  44. android:layout_height="match_parent"
  45. android:layout_weight="1"
  46. android:clickable="true"
  47. android:gravity="center"
  48. android:textColor="#0679FE"
  49. android:textSize="@dimen/sp_14"
  50. tools:text="取消" />
  51. <View
  52. android:id="@+id/common_dialog_vertical_line"
  53. android:layout_width="1dp"
  54. android:layout_height="match_parent"
  55. android:background="#F5F5F5" />
  56. <TextView
  57. android:id="@+id/common_dialog_confirm_tv"
  58. android:layout_width="0dp"
  59. android:layout_height="match_parent"
  60. android:layout_weight="1"
  61. android:clickable="true"
  62. android:gravity="center"
  63. android:textColor="#0679FE"
  64. android:textSize="@dimen/sp_14"
  65. tools:text="确定" />
  66. </LinearLayout>
  67. </LinearLayout>

7.gble_layout蓝牙布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="#91CEC7"
  8. android:orientation="vertical">
  9. <RelativeLayout
  10. android:layout_width="match_parent"
  11. android:layout_height="@dimen/dp_40"
  12. android:layout_marginTop="@dimen/dp_5"
  13. android:gravity="center_vertical"
  14. android:orientation="horizontal">
  15. <LinearLayout
  16. android:id="@+id/finish"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:layout_marginLeft="@dimen/dp_15"
  20. android:gravity="center_vertical"
  21. android:orientation="horizontal">
  22. <ImageView
  23. android:layout_width="@dimen/dp_25"
  24. android:layout_height="@dimen/dp_20"
  25. android:scaleType="fitCenter"
  26. android:src="@mipmap/back" />
  27. <TextView
  28. android:layout_width="wrap_content"
  29. android:layout_height="wrap_content"
  30. android:layout_marginLeft="@dimen/dp_10"
  31. android:gravity="center_vertical"
  32. android:text="返回"
  33. android:textColor="#666666"
  34. android:textAlignment="center"
  35. android:textSize="@dimen/sp_18"
  36. tools:ignore="RtlCompat" />
  37. </LinearLayout>
  38. <LinearLayout
  39. android:layout_width="match_parent"
  40. android:layout_height="wrap_content"
  41. android:layout_weight="1"
  42. android:gravity="center">
  43. <TextView
  44. android:layout_width="wrap_content"
  45. android:layout_height="wrap_content"
  46. android:gravity="center_vertical"
  47. android:text="蓝牙搜索"
  48. android:textColor="#666666"
  49. android:textAlignment="center"
  50. android:textSize="@dimen/sp_18"
  51. tools:ignore="RtlCompat" />
  52. </LinearLayout>
  53. </RelativeLayout>
  54. <LinearLayout
  55. android:layout_width="match_parent"
  56. android:layout_height="wrap_content"
  57. android:layout_marginLeft="@dimen/dp_30"
  58. android:layout_marginRight="@dimen/dp_30"
  59. android:layout_marginBottom="@dimen/dp_50"
  60. android:background="@drawable/blelist_bg_shape"
  61. android:orientation="vertical">
  62. <LinearLayout
  63. android:layout_width="match_parent"
  64. android:layout_height="wrap_content"
  65. android:layout_marginLeft="@dimen/dp_30"
  66. android:layout_marginTop="@dimen/dp_30"
  67. android:layout_marginRight="@dimen/dp_30"
  68. android:layout_marginBottom="@dimen/dp_5"
  69. android:background="#ffffff"
  70. android:orientation="horizontal">
  71. <TextView
  72. android:layout_width="wrap_content"
  73. android:layout_height="wrap_content"
  74. android:layout_weight="1"
  75. android:text=""
  76. android:textSize="@dimen/sp_16" />
  77. <Switch
  78. android:id="@+id/switch_bt"
  79. android:layout_width="wrap_content"
  80. android:layout_height="wrap_content"
  81. android:thumb="@drawable/thumb_bg"
  82. android:track="@drawable/track_bg"
  83. tools:ignore="UseSwitchCompatOrMaterialXml" />
  84. </LinearLayout>
  85. <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
  86. android:id="@+id/swipeLayout"
  87. android:layout_width="match_parent"
  88. android:layout_height="match_parent"
  89. android:layout_marginBottom="60dp"
  90. android:layout_weight="1"
  91. android:background="#ffffff">
  92. <androidx.recyclerview.widget.RecyclerView
  93. android:id="@+id/recycleview"
  94. android:layout_width="match_parent"
  95. android:layout_height="match_parent"
  96. android:layout_marginTop="13dp" />
  97. </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
  98. </LinearLayout>
  99. <ScrollView
  100. android:layout_width="match_parent"
  101. android:layout_height="match_parent"
  102. android:orientation="vertical">
  103. <LinearLayout
  104. android:layout_width="match_parent"
  105. android:layout_height="match_parent"
  106. android:orientation="vertical">
  107. <TextView
  108. android:layout_width="match_parent"
  109. android:layout_height="@dimen/dp_30"
  110. android:layout_marginLeft="@dimen/dp_10"
  111. android:layout_marginRight="@dimen/dp_10"
  112. android:text="接收蓝牙数据" />
  113. <TextView
  114. android:id="@+id/blue_txt"
  115. android:layout_width="match_parent"
  116. android:layout_height="wrap_content"
  117. android:layout_marginLeft="@dimen/dp_10"
  118. android:layout_marginRight="@dimen/dp_10"
  119. android:text="" />
  120. </LinearLayout>
  121. </ScrollView>
  122. </LinearLayout>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/549281
推荐阅读
相关标签
  

闽ICP备14008679号