Android蓝牙ble扫描
来源:互联网 发布:gis空间数据库 编辑:程序博客网 时间:2024/04/29 04:08
酒已经准备好了,各位看客,请准备好小板凳。
理论性的东西就不写太多了,推荐一个挺好的博文
http://www.jianshu.com/p/de82f411a7fc
官方文档的翻译(简书):
http://www.jianshu.com/p/bc408af3dd92
复制一些重要的理论过来,也方便你们查看:
扫盲
- 蓝牙有传统蓝牙(3.0以下)和低功耗蓝牙(ble,又称蓝牙4.0)之分
- android手机必须系统版本4.3及以上才支持BLE API。低功耗蓝牙较传统蓝牙, 传输速度更快,覆盖范围更广,安全性更高,延迟更短,耗电极低等等优点,这也是为什么近年来智能穿戴的东西越来越多,越来越火
- 传统蓝牙与低功耗蓝牙通信方式也有所不同,传统的一般通过socket方式,而低功耗蓝牙是通过Gatt协议来实现
- 低功耗蓝牙也叫BLE
二、解释:
BLE分为Service、Characteristic、Descriptor三部分,每个部分都拥有不同的 UUID来标识
3通信数据一般存储在Characteristic内,目前一个Characteristic中存储的数据最大为20 byte
4与Characteristic相关的权限字段主要有READ、WRITE、WRITE_NO_RESPONSE、NOTIFY。 Characteristic具有的权限属性可以有一个或者多个
非常感谢作者对知识的分享
这篇只会介绍Android蓝牙4.0Ble的扫描,大大们,请。。。。。
效果图先奉上,直接拍个照
酒喝完了,上菜
在6.0版本前,使用蓝牙功能,只需要配置下面的权限即可:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
6.0以后
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
添加动态权限
下面是ActivityMain的布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/startScale" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="startScale" /> <Button android:id="@+id/stopScale" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="stopScale" /> <ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="stopScale"/> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent"></ListView></LinearLayout>
package com.ityingli.www.bluetoothtest2;import android.Manifest;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothManager;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.location.LocationManager;import android.os.Build;import android.os.Bundle;import android.os.Handler;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final int REQUEST_CODE_LOCATION_SETTINGS = 2; //用于Gps打开 private BluetoothManager bluetoothManager; //蓝牙管理器 private BluetoothAdapter bluetoothAdapter; //蓝牙适配器 private Boolean scaleIng ; //是否正在扫描 private static final int REQUEST_ENABLE_BLE = 1; //蓝牙请求 private static final long SCALE_PERIOD= 10*1000; //扫描时长 10秒 //布局中的控件 private Button startScaleButton,stopScaleButton; //开始扫描按钮,停止扫描按钮 private ListView listview; //展示扫描到的结果Listview; private List<BlueTooth_item__Bean> BlueToothDevice_Info; //蓝牙设备的信息 private ListViewAdapter adapter; private ProgressBar progressbar; private Handler handler; private static final int REQUEST_CODE_ACCESS_COARSE_LOCATION = 1; //动态申请权限 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //初始化控件 initEvent(); //初始化事件 initData(); //初始化数据 adapter = new ListViewAdapter(MainActivity.this,BlueToothDevice_Info); //listView的适配器 listview.setAdapter(adapter); //检测当前设备是否支持蓝牙ble if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){ Toast.makeText(MainActivity.this, "当前蓝牙不支持蓝牙设备", Toast.LENGTH_SHORT).show(); finish(); } //通过蓝牙管理器得到一个蓝牙适配器 bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); if(bluetoothAdapter==null){ Toast.makeText(MainActivity.this,"该设备不支持蓝牙",Toast.LENGTH_SHORT).show(); } //android6.0之后要求有定位权限才可以扫描到蓝牙 //动态申请权限 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){ //如果api版本大于23Android6.0的时候 //判断是否具有权限 if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)!=PackageManager.PERMISSION_GRANTED){ //判断是否需要向用户解释为什么需要申请权限 if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_COARSE_LOCATION)){ Toast.makeText(MainActivity.this,"需要获取定位才可以使用BLE扫描",Toast.LENGTH_SHORT).show(); } //请求权限 ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_CODE_ACCESS_COARSE_LOCATION);//请求码 } } } // //执行完上面的请求权限后,系统会弹出提示框让用户选择是否允许改权限。选择的结果可以在回到接口中得知: @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode==REQUEST_CODE_ACCESS_COARSE_LOCATION){ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //用户允许改权限,0表示允许,-1表示拒绝 PERMISSION_GRANTED = 0, PERMISSION_DENIED = -1 //permission was granted, yay! Do the contacts-related task you need to do. //这里进行授权被允许的处理 } else { //permission denied, boo! Disable the functionality that depends on this permission. //这里进行权限被拒绝的处理 } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } //以上就是如何在应用运行的过程中申请位置权限。做完上面你以为就 OK 了,但是可能你会发现,并没有什么卵用,依然不能搜索到周围的 Ble 设备,原因是可能的你的位置服务(定位 GPS)没有打开。 //检测定位是否打开 public static final boolean isLocationEnable(Context context) { LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); boolean networkProvider = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); boolean gpsProvider = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (networkProvider || gpsProvider) return true; return false; } //如果没有就打开,进入定位设置界面,让用户自己选择是否打开定位。选择的结果获取: private void setLocationService() { Intent locationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); this.startActivityForResult(locationIntent, REQUEST_CODE_LOCATION_SETTINGS); } @Override protected void onResume() { super.onResume(); //确保蓝牙可以使用,如果不可以使用一个弹窗 if(!bluetoothAdapter.enable()){ Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(intent,REQUEST_ENABLE_BLE); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //不同打开蓝牙 if(requestCode ==REQUEST_ENABLE_BLE && resultCode == RESULT_CANCELED){ finish(); return; } //定位 if (requestCode == REQUEST_CODE_LOCATION_SETTINGS) { if (isLocationEnable(this)) { //定位已打开的处理 } else { //定位依然没有打开的处理 Toast.makeText(MainActivity.this,"请打开GPS",Toast.LENGTH_SHORT).show(); } } else super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data); } private void initData() { //用于定时取消扫描 handler = new Handler(); //模拟蓝牙设备的信息 BlueToothDevice_Info = new ArrayList<>(); for(int i = 0 ;i<10;i++){ BlueTooth_item__Bean bluetooth_device_item_info = new BlueTooth_item__Bean(); bluetooth_device_item_info.blueToothDevie_Name = "蓝牙设备名字"+i; bluetooth_device_item_info.blueToothDevie_Adress = "蓝牙设备mac地址"+i; BlueToothDevice_Info.add(bluetooth_device_item_info); } } private void initEvent() { startScaleButton.setOnClickListener(this); //开始扫描事件 stopScaleButton.setOnClickListener(this); //停止扫描 } private void initView() { startScaleButton = (Button)findViewById(R.id.startScale); //初始化控件。开始扫描按钮 stopScaleButton= (Button)findViewById(R.id.stopScale); //初始化控件,停止扫描按钮 listview = (ListView) findViewById(R.id.listview); //用于展示扫描到的设备信息,Listview progressbar = (ProgressBar) findViewById(R.id.progressbar); progressbar.setVisibility(View.GONE); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.startScale: //扫描操作 (扫描一定的事件就自动关闭扫描) BlueToothDevice_Info.clear(); progressbar.setVisibility(View.VISIBLE); bluetoothAdapter.startLeScan(scaleCallback); handler.postDelayed(new Runnable() { @Override public void run() { bluetoothAdapter.stopLeScan(scaleCallback); progressbar.setVisibility(View.GONE); } },10000); break; case R.id.stopScale: //停止扫描 progressbar.setVisibility(View.GONE); bluetoothAdapter.stopLeScan(scaleCallback); break; } } //扫描到设备之后的回调方法 private BluetoothAdapter.LeScanCallback scaleCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { if(device.getName()!=null && device.getAddress()!=null) { runOnUiThread(new Runnable() { @Override public void run() { final BlueTooth_item__Bean bean = new BlueTooth_item__Bean(); bean.blueToothDevie_Name = device.getName(); bean.blueToothDevie_Adress = device.getAddress(); if(BlueToothDevice_Info.contains(bean)) { //如果集合中已经包含相同的对象,则不添加进去 }else{ BlueToothDevice_Info.add(bean); adapter.notifyDataSetChanged(); } } }); } } };}
Listview的适配器
package com.ityingli.www.bluetoothtest2;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;import java.util.List;/** * Created by Administrator on 2017/7/29. */public class ListViewAdapter extends BaseAdapter { private Context mcontext; //上下文 private List<BlueTooth_item__Bean> listDatas; //listview需要用到的信息包括蓝牙名字和蓝牙设备的mac地址; private LayoutInflater layoutInflater; ListViewAdapter(Context mcontext, List<BlueTooth_item__Bean> listDatas){ this.mcontext = mcontext; this.listDatas = listDatas; layoutInflater = LayoutInflater.from(mcontext); } @Override public int getCount() { return listDatas.size(); } @Override public Object getItem(int position) { return listDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View view, ViewGroup parent) { ListviewHolder listviewHolder; if(view ==null){ listviewHolder = new ListviewHolder(); view = layoutInflater.inflate(R.layout.layout_listview_item,null); listviewHolder.device_Name = (TextView) view.findViewById(R.id.device_name); listviewHolder.device_Address= (TextView) view.findViewById(R.id.device_address); view.setTag(listviewHolder); }else{ listviewHolder = (ListviewHolder) view.getTag(); } listviewHolder.device_Name.setText(listDatas.get(position).blueToothDevie_Name); listviewHolder.device_Address.setText(listDatas.get(position).blueToothDevie_Adress); return view; } static class ListviewHolder{ private TextView device_Name; private TextView device_Address; }}
适配器中用的的布局(ListView的Item的布局)
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/device_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="蓝牙设备名字" android:layout_margin="2dp" /> <TextView android:id="@+id/device_address" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="蓝牙设备的名字" android:layout_margin="5dp" /></LinearLayout>
一个实体类,主要是蓝牙设备的name和address;
package com.ityingli.www.bluetoothtest2;/** * Created by Administrator on 2017/7/29. */public class BlueTooth_item__Bean { //该数据用于listview的item String blueToothDevie_Name; String blueToothDevie_Adress; //蓝牙设备的名字和mas地址 //判断内容是否相等 @Override public boolean equals(Object obj) { if(obj instanceof BlueTooth_item__Bean){ if(blueToothDevie_Adress.equals(((BlueTooth_item__Bean) obj).blueToothDevie_Adress) && blueToothDevie_Name.equals(((BlueTooth_item__Bean) obj).blueToothDevie_Name)){ return true; } }else{ return false; } return super.equals(obj); } @Override public int hashCode() { return blueToothDevie_Adress.hashCode(); }}
注释也是挺详细的了,各位晚安,不早了 2017/7/30 0:53
阅读全文
0 0
- Android蓝牙ble扫描
- android BluetoothAdapter蓝牙BLE扫描总结
- Android 低功耗蓝牙(BLE)开发(4)-- 蓝牙扫描和连接
- Android 蓝牙 BLE蓝牙 浅析
- android 蓝牙BLE
- Android蓝牙4.0BLE
- android!蓝牙BLE
- Android ble 蓝牙4.0
- Android BLE蓝牙通信
- android 蓝牙BLE
- Android:使用BLE蓝牙
- android BLE蓝牙
- Android Ble蓝牙开发
- 浅谈 Android BLE蓝牙
- android 蓝牙Ble详解
- android 蓝牙BLE思路
- android BLE蓝牙开发
- Android BLE蓝牙4.0
- Bovine Genomics
- 面向对象5
- 51nod 1418 放球游戏
- Xamarin.Forms判断网络连接情况
- 配置树莓派连接WiFi
- Android蓝牙ble扫描
- 【Github】如何取消已fork的repository
- Linux下Mysql的安装
- switch_caller_profile中的times变量结构
- uva11025--二进制枚举
- 线程的创建、等待、终止、分离
- Hdu 5873 Football Games 推理(XJBC
- Python中dict用法详解
- Java中的类