最近在做蓝牙扫描功能,了解了蓝牙的一部分知识,虽然不够深入,但是感觉良好,没做的时候感觉非常难:
但是做完了以后感觉 其他并不难 希望看到此篇文章的你---加油
需要时这样:开启扫描蓝牙周围设备,拿到MAC地址已经广播包数据,下面我们来写一下代码
先来看一下效果
大概流程如下
1.添加权限
2.判断设备是否支持BLE4.0
3.判断蓝牙是否开启,如果未开启,则静默开启窗口
4.开启后,开始进行蓝牙扫描
5.通过BluetoothAdapter.LeScanCallback获取扫描结果
如果这些代码都写在V层那就有些过于臃肿了,所以我们来写一个工具类
建立BlueUtils.java
public class BlueUtils {
//蓝牙适配器
private BluetoothAdapter mBluetoothAdapter;
//搜索状态的标示
private boolean mScanning = true;
//蓝牙适配器List
private List<BluetoothDevice> mBlueList;
//上下文
private Context context;
//单例模式
private static BlueUtils blueUtils;
//蓝牙的回调地址
private BluetoothAdapter.LeScanCallback mLesanCall;
//扫描执行回调
private BlueUddtils.Callback callback;
}
先把变量都写好 下面咱们开始写方法
先写一个单例模式
//单例模式
public static BlueUtils getBlueUtils(){
if(blueUtils == null){
blueUtils = new BlueUtils();
}
return blueUtils;
}
然后getInitialization方法中初始化一些蓝牙的相关类
/***
* 初始化蓝牙的一些信息
*/
public void getInitialization(Context context){
this.context = context;
//初始化蓝牙适配器
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
//初始化蓝牙
mBluetoothAdapter = bluetoothManager.getAdapter();
//初始化List
mBlueList = new ArrayList<>();
//实例化蓝牙回调
mLesanCall = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
//返回三个对象 分类别是 蓝牙对象 蓝牙信号强度 以及蓝牙的广播包
if(!mBlueList.contains(bluetoothDevice)){
mBlueList.add(bluetoothDevice);
}
}
};
}
接下来我们就要写开始扫描和关闭的方法了
/**
* 开启蓝牙
*/
public void startBlue(){
if(mScanning){
mScanning = false;
//开始扫描并设置回调
mBluetoothAdapter.startLeScan(mLesanCall);
}
}
/**
* 停止蓝牙扫描
*/
public void stopBlue(){
if(!mScanning){
//结束蓝牙扫描
mBluetoothAdapter.stopLeScan(mLesanCall);
}
}
设置接口回调
/**
* 接口回调
*/
public interface Callbacks{
void CallbackList(List<BluetoothDevice> mBlueLis);
}
/**
* 设置接口回调
* @param callback 自身
*/
public void setCallback(Callbacks callback) {
this.callback = callback;
}
大家需要注意的是,蓝牙扫描到设备就会回调onLeScan方法 所以我们需要在此方法中把搜索到的蓝牙对象加入到List中,然后利用接口回调把数据送出去
//实例化蓝牙回调
mLesanCall = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
//返回三个对象 分类别是 蓝牙对象 蓝牙信号强度 以及蓝牙的广播包
if(!mBlueList.contains(bluetoothDevice)){//重复的则不添加
mBlueList.add(bluetoothDevice);
//接口回调
callback.CallbackList(mBlueList);
}
}
};
还有isSupportBlue方法是用来检测设备是否支持蓝牙的
/**
* 判断是否支持蓝牙
* @return
*/
public boolean isSupportBlue(){
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
return true;
}else {
return false;
}
}
/**
* 返回蓝牙对象
* @return
*/
public BluetoothAdapter getmBluetoothAdapter() {
return mBluetoothAdapter;
}
下面我们开始调用吧 在调用之前,我们需要给程序加入蓝牙权限,(6.0以后需要动态申请)
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
先贴布局文件
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_weight="1"
android:id="@+id/scan"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="搜索" />
<Button
android:layout_weight="1"
android:id="@+id/end"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="关闭扫描" />
</LinearLayout>
<ListView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
大体布局如下
MainActivity.java
package com.example.myapplication;
import android.bluetooth.BluetoothDevice;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import com.example.myapplication.adapter.BlueAdapter;
import java.util.List;
/**
* Created by huitao on 2017/12/27.
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
//搜索BUTTON
private Button scan,end;
//搜索结果List
private ListView resultList;
//蓝牙工具类
private BlueUtils blueUtils;
//蓝牙的Adapter
private BlueAdapter blueAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
blueUtils = new BlueUtils();
//初始化工具类
blueUtils.getInitialization(this);
//判断是否支持蓝牙
if (!blueUtils.isSupportBlue()) {
Toast.makeText(this, "设备支持蓝牙4.0", Toast.LENGTH_SHORT).show();
blueUtils.getmBluetoothAdapter().enable();
}else {
Toast.makeText(this, "设备不支持蓝牙4.0", Toast.LENGTH_SHORT).show();
//静默开启蓝牙
}
inint();
}
/**
* 初始化数据
*/
private void inint() {
scan = findViewById(R.id.scan);
end = findViewById(R.id.end);
resultList = findViewById(R.id.result);
scan.setOnClickListener(this);
end.setOnClickListener(this);
blueUtils.setCallback(new BlueUtils.Callbacks() {
@Override
public void CallbackList(List<BluetoothDevice> mBlueLis) {
//我们在此处设置Adapter
if(blueAdapter == null){
blueAdapter = new BlueAdapter(mBlueLis,MainActivity.this);
resultList.setAdapter(blueAdapter);
}else {
blueAdapter.notifyDataSetChanged();
}
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.scan:
blueUtils.startBlue();
Toast.makeText(this, "开启成功", Toast.LENGTH_SHORT).show();
break;
case R.id.end:
blueUtils.stopBlue();
Toast.makeText(this, "关闭成功", Toast.LENGTH_SHORT).show();
break;
}
}
}
BlueAdapter.java
package com.example.myapplication.adapter;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
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 com.example.myapplication.R;
import java.util.List;
/**
* 蓝牙填充
* Created by huitao on 2017/12/27.
*/
public class BlueAdapter extends BaseAdapter{
private List<BluetoothDevice> mBluelist;
private LayoutInflater layoutInflater;
public BlueAdapter(List<BluetoothDevice> list, Context context) {
mBluelist = list;
layoutInflater = LayoutInflater.from(context);//context :要使用当前的Adapter的界面对象 layoutInflater: 布局装载器对象
}
@Override
public int getCount() {
return mBluelist.size();
}
@Override
public Object getItem(int i) {
return mBluelist.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@SuppressLint("SetTextI18n")
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
view = layoutInflater.inflate(R.layout.list_item,null);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice blueDevice = mBluelist.get(i);
final String deviceName = blueDevice.getName();
if (deviceName != null && deviceName.length() > 0) {
viewHolder.deviceName.setText(blueDevice.getName());
} else {
viewHolder.deviceName.setText("未知设备");
}
viewHolder.deviceAddress.setText("MAC地址:"+blueDevice.getAddress());
return view;
}
class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
}
adapter的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/device_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24dp"/>
<TextView android:id="@+id/device_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12dp"/>
</LinearLayout>
最后说一下 BluetoothDevice获取信息的方法
getName 是获取设备名字
getAddress 是获取设备的MAC地址
getBluetoothClass().getDeviceClass 是获取设备的类型
到此就结束了 感谢大家