安卓蓝牙BLE(1)

最近项目中有用到和硬件手环交互的功能。手环是一个BLE手环,需要用到蓝牙技术。

1.在AndroidManifest.xml中添加权限:

	<uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

2.动态权限获取:(这个必须加,不然会导致搜索设备的回调不被调用)

//清单文件里面也需要配置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.CAMERA,}, 0);
        }

    //系统方法,从requestPermissions()方法回调结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //确保是我们的请求
        if (requestCode == REQUEST_COARSE_LOCATION) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限被授予", Toast.LENGTH_SHORT).show();
            } else if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

3.获取BluetoothManager管理者:

BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

4.获取BluetoothAdapter对象:

mBluetoothAdapter = bluetoothManager.getAdapter();
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {

            Intent enableBluetooth = new Intent(

                    BluetoothAdapter.ACTION_REQUEST_ENABLE);

            startActivityForResult(enableBluetooth, 1);
        }

5.开始搜索设备设置回调,当有设备被搜索到时 就会回调此方法:

mBluetoothAdapter.startLeScan(mLeScanCallback);

    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override

        public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
            try {
                int startByte = 2;
                boolean patternFound = false;
                while (startByte <= 5) {

                    if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && // Identifies
                            ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { // Identifies
                        patternFound = true;

                        break;

                    }

                    startByte++;

                }

                // 如果找到了的话

                if (patternFound) {

                    // 转换为16进制

                    byte[] uuidBytes = new byte[16];

                    System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);

                    String hexString = bytesToHex(uuidBytes);


                    // ibeacon的UUID值

                    String uuid = hexString.substring(0, 8) + "-"

                            + hexString.substring(8, 12) + "-"

                            + hexString.substring(12, 16) + "-"

                            + hexString.substring(16, 20) + "-"

                            + hexString.substring(20, 32);


                    // ibeacon的Major值

                    int major = (scanRecord[startByte + 20] & 0xff) * 0x100

                            + (scanRecord[startByte + 21] & 0xff);


                    // ibeacon的Minor值

                    int minor = (scanRecord[startByte + 22] & 0xff) * 0x100

                            + (scanRecord[startByte + 23] & 0xff);


                    String ibeaconName = device.getName();

                    String mac = device.getAddress();

                    int txPower = (scanRecord[startByte + 24]);
                        Log.i("lee", "   Name:" + ibeaconName + "   Mac:" + mac + "   UUID:" + uuid + "   Major:" + major + "   Minor:" + minor + "   TxPower:" + txPower + "   rssi:" + rssi);
               
                }
            } catch (Exception e) {
            }
        }
    };

当有设备被搜索到时就会回调这个方法,第一个参数是设备,第二个参数是rssi,代表信号强度,第三个参数scanRecord是广播包数据。此处写了一个过滤,当是ibeacon设备时就会进入if语句中打印出该ibeacon设备的信息。

全部代码:

package com.demo.ibeacondemo;

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

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.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import java.util.Date;

public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;
    private static final int REQUEST_COARSE_LOCATION = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        isLocationOpen();
        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {

            Intent enableBluetooth = new Intent(

                    BluetoothAdapter.ACTION_REQUEST_ENABLE);

            startActivityForResult(enableBluetooth, 1);
        }
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    }

    static final char[] hexArray = "0123456789ABCDEF".toCharArray();

    private void isLocationOpen() {
        //清单文件里面也需要配置
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.CAMERA,}, 0);
        }
    }

    //系统方法,从requestPermissions()方法回调结果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //确保是我们的请求
        if (requestCode == REQUEST_COARSE_LOCATION) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限被授予", Toast.LENGTH_SHORT).show();
            } else if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    private static String bytesToHex(byte[] bytes) {

        char[] hexChars = new char[bytes.length * 2];

        for (int j = 0; j < bytes.length; j++) {

            int v = bytes[j] & 0xFF;

            hexChars[j * 2] = hexArray[v >>> 4];

            hexChars[j * 2 + 1] = hexArray[v & 0x0F];

        }

        return new String(hexChars);

    }

    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override

        public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
            try {
                int startByte = 2;
                boolean patternFound = false;
                while (startByte <= 5) {

                    if (((int) scanRecord[startByte + 2] & 0xff) == 0x02 && // Identifies
                            ((int) scanRecord[startByte + 3] & 0xff) == 0x15) { // Identifies

                        patternFound = true;

                        break;

                    }

                    startByte++;

                }

                // 如果找到了的话

                if (patternFound) {

                    // 转换为16进制

                    byte[] uuidBytes = new byte[16];

                    System.arraycopy(scanRecord, startByte + 4, uuidBytes, 0, 16);

                    String hexString = bytesToHex(uuidBytes);


                    // ibeacon的UUID值

                    String uuid = hexString.substring(0, 8) + "-"

                            + hexString.substring(8, 12) + "-"

                            + hexString.substring(12, 16) + "-"

                            + hexString.substring(16, 20) + "-"

                            + hexString.substring(20, 32);


                    // ibeacon的Major值

                    int major = (scanRecord[startByte + 20] & 0xff) * 0x100

                            + (scanRecord[startByte + 21] & 0xff);


                    // ibeacon的Minor值

                    int minor = (scanRecord[startByte + 22] & 0xff) * 0x100

                            + (scanRecord[startByte + 23] & 0xff);


                    String ibeaconName = device.getName();

                    String mac = device.getAddress();

                    int txPower = (scanRecord[startByte + 24]);
                    Log.i("lee", "   Name:" + ibeaconName + "   Mac:" + mac + "   UUID:" + uuid + "   Major:" + major + "   Minor:" + minor + "   TxPower:" + txPower + "   rssi:" + rssi);
                }

            } catch (Exception e) {

            }
        }
    };
}

以上就能完成搜索设备的功能。

猜你喜欢

转载自blog.csdn.net/qq77485042/article/details/109286036