Android BLE蓝牙开发(一)—扫描并显示结果

一、权限

<!-- 使用蓝牙的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 扫描蓝牙设备或者操作蓝牙设置 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- 精确定位权限,在Android6.0及以上使用,蓝牙扫描需要用到这个的动态权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 模糊定位权限,在Android6.0及以上使用,蓝牙扫描需要用到这个的动态权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

二、获取BluetoothAdapter实例

BLe蓝牙获取BluetoothAdapter实例不同与经典蓝牙一样,首先得通过系统服务getSystemService(BLUETOOTH_SERVICE)获取BluetoothManager的实例,然后再通过BluetoothManager的getAdapter方法获取BluetoothAdapter实例。
代码:

 	private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager mBluetoothManager;

	mBluetoothManager=(BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
    mBluetoothAdapter=mBluetoothManager.getAdapter();

三、判断设备是否支持BLE蓝牙并使能蓝牙打开

mBluetoothManager.getAdapter()返回null值就是设备不支持BLE蓝牙,mBluetoothAdapter.isEnable()方法返回true代表蓝牙已打开,返回false代表关闭。通过Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)可以拉起打开蓝牙的弹窗

if(mBluetoothAdapter!=null){
            if(!mBluetoothAdapter.isEnabled()){
                Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(intent,1);
            }
        }

四、自定义BLE蓝牙扫描结果的Adapter

package com.example.bledemo.adapter;

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.bledemo.R;

import java.util.List;

public class BleAdapter extends BaseAdapter {

    private List<BluetoothDevice> mDeviceList;
    private Context mContext;
    private LayoutInflater mInflater;

    public BleAdapter(List<BluetoothDevice> deviceList,Context context){
        this.mDeviceList=deviceList;
        this.mContext=context;
        this.mInflater=LayoutInflater.from(this.mContext);
    }

    @Override
    public int getCount() {
        return mDeviceList.size();
    }

    @Override
    public Object getItem(int position) {
        return mDeviceList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHandler viewHandler;
        if(convertView==null){
            viewHandler=new ViewHandler();
            convertView=mInflater.inflate(R.layout.list_ble_device,null);
            viewHandler.textView=convertView.findViewById(R.id.ble_device);
            convertView.setTag(viewHandler);
        }else{
            viewHandler=(ViewHandler)convertView.getTag();
        }

        viewHandler.textView.setText(mDeviceList.get(position).getName());

        return convertView;
    }

    private class ViewHandler{
        TextView textView;
    }
}

五、编写蓝牙扫描到设备的回调

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            if(!mDeviceList.contains(device)){
                mDeviceList.add(device);
                mBleAdapter.notifyDataSetChanged();
            }
        }
    };

六、开启扫描

1、先实现动态权限的获取

String[] permissions={Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION};
int checkSum=0;
for(String permission:permissions){
	checkSum+=checkSelfPermission(permission);
}
if(checkSum!=0){
	requestPermissions(permissions,1);
}

2、清理数据并开启扫描

mDeviceList.clear();
            mBleAdapter.notifyDataSetChanged();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mBluetoothAdapter.startLeScan(leScanCallback);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mBluetoothAdapter.stopLeScan(leScanCallback);
                }
            }).start();

七、完整代码

1、AndroidManifest.XML

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bledemo">

    <uses-permission android:name="android.permission.BLUETOOTH" />

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.BleDemo">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

2、activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="扫描"
        android:layout_gravity="center"
        android:onClick="onScanBluetooth"/>

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/ble_list"/>

</LinearLayout>

3、list_ble_device.xml

<?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="horizontal">

    <View
        android:layout_width="30dp"
        android:layout_height="0dp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/ble_device"/>

</LinearLayout>

4、MainActivity.java

package com.example.bledemo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;

import com.example.bledemo.adapter.BleAdapter;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager mBluetoothManager;

    private List<BluetoothDevice> mDeviceList=new ArrayList<>();
    private ListView mListView;
    private BleAdapter mBleAdapter;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBluetoothManager=(BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
        mBluetoothAdapter=mBluetoothManager.getAdapter();

        if(mBluetoothAdapter!=null){
            if(!mBluetoothAdapter.isEnabled()){
                Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(intent,1);
            }
        }
        mListView=findViewById(R.id.ble_list);
        mBleAdapter=new BleAdapter(mDeviceList,this);
        mListView.setAdapter(mBleAdapter);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable @org.jetbrains.annotations.Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public void onScanBluetooth(View view) {
        if(mBluetoothAdapter!=null&&mBluetoothAdapter.isEnabled()){
            String[] permissions={Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION};
            int checkSum=0;
            for(String permission:permissions){
                checkSum+=checkSelfPermission(permission);
            }
            if(checkSum!=0){
                requestPermissions(permissions,1);
            }

            mDeviceList.clear();
            mBleAdapter.notifyDataSetChanged();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mBluetoothAdapter.startLeScan(leScanCallback);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mBluetoothAdapter.stopLeScan(leScanCallback);
                }
            }).start();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            if(!mDeviceList.contains(device)){
                mDeviceList.add(device);
                mBleAdapter.notifyDataSetChanged();
            }
        }
    };

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

5、BleAdapter.java

package com.example.bledemo.adapter;

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.bledemo.R;

import java.util.List;

public class BleAdapter extends BaseAdapter {

    private List<BluetoothDevice> mDeviceList;
    private Context mContext;
    private LayoutInflater mInflater;

    public BleAdapter(List<BluetoothDevice> deviceList,Context context){
        this.mDeviceList=deviceList;
        this.mContext=context;
        this.mInflater=LayoutInflater.from(this.mContext);
    }

    @Override
    public int getCount() {
        return mDeviceList.size();
    }

    @Override
    public Object getItem(int position) {
        return mDeviceList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHandler viewHandler;
        if(convertView==null){
            viewHandler=new ViewHandler();
            convertView=mInflater.inflate(R.layout.list_ble_device,null);
            viewHandler.textView=convertView.findViewById(R.id.ble_device);
            convertView.setTag(viewHandler);
        }else{
            viewHandler=(ViewHandler)convertView.getTag();
        }

        viewHandler.textView.setText(mDeviceList.get(position).getName());

        return convertView;
    }

    private class ViewHandler{
        TextView textView;
    }
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

szzyjsxyzwy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值