Configuración de la aplicación Android de comunicación STM32 y BLE Bluetooth (1)

La dificultad de las cosas es mucho menor que el miedo a las cosas.

0. Prefacio

Recientemente completé una aplicación simple basada en la comunicación Bluetooth BLE, registrada aquí para su referencia, con la esperanza de resolver dudas para quienes lo necesiten. Hay un total de dos interfaces en esta aplicación. La primera interfaz se da cuenta de encender Bluetooth, apagar Bluetooth, escanear Bluetooth y mostrar los resultados del escaneo. Al seleccionar el dispositivo Bluetooth escaneado para saltar a la segunda interfaz, y el Bluetooth seleccionado en el procesar de nuevo El dispositivo se conecta y obtiene el servicio. El estado de la conexión se muestra en la segunda interfaz, y los datos se pueden enviar y recibir. ¡Este código solo realiza la función más básica de la transmisión de datos Bluetooth, y se puede llevar a cabo más desarrollo de acuerdo con las necesidades reales sobre esta base!

1. Obtener permiso

En primer lugar, el primer paso es obtener permisos de Bluetooth y permisos de ubicación Androi 6.0(API 23). No solo necesita agregar permisos de forma estática ( AndroidMainfest.xmlconfigurados en), sino que también necesita obtener permisos de forma dinámica en el programa. Los siguientes son algunos permisos que deben obtenerse dinámicamente.

grupo de afiliación permisos
calendario LEER_CALENDARIO
calendario ESCRIBIR_CALENDARIO
cámara CÁMARA
Persona de contacto LEER_CONTACTOS
Persona de contacto ESCRIBIR_CONTACTOS
Persona de contacto OBTENER_CONTACTOS
Ubicación ACCESO_FINE_LOCATION
Ubicación ACCESO_COARSE_LOCATION
micrófono GRABAR AUDIO
Teléfono LEER_TELÉFONO_ESTADO
Teléfono LLAMADA TELEFÓNICA
Teléfono LEER_LLAMADA_REGISTRO
Teléfono ESCRIBIR_LLAMADA_REGISTRO
Teléfono ADD_CORREO DE VOZ
Teléfono USO_SIP
Teléfono PROCESAR_LLAMADAS_SALIENTES
sensor CUERPO_SENSORES
Mensaje corto ENVIAR SMS
Mensaje corto RECIBIR_SMS
Mensaje corto LEER_SMS
Mensaje corto RECEICE_WAP_PUSH
Mensaje corto RECIBIR_MMS
Mensaje corto LEER_ALMACENAMIENTO_EXTERNO
Mensaje corto ESCRIBIR_ALMACENAMIENTO_EXTERNO

Nota: si una aplicación solicita un permiso peligroso enumerado AndroidManifest.xmlen , y la aplicación ya tiene otro permiso peligroso en el mismo grupo de permisos, el sistema otorga el permiso de inmediato, sin ninguna interacción por parte del usuario. Por ejemplo, si una aplicación solicitó y se le otorgó ACCESS_FINE_LOCATIONun permiso , y luego lo solicita ACCESS_COARSE_LOCATION(pertenece al mismo grupo de ubicación), el sistema otorgará el permiso de inmediato y no aparecerán más cuadros de diálogo solicitando la concesión del permiso.

ACCESS_FINE_LOCATIONEn este artículo , se utilizan ACCESS_COARSE_LOCATIONpermisos peligrosos y permisos normales . Primero, BLUETOOTHdebe agregar permisos de forma estática al archivo:BLUETOOTH_ADMINAndroidMainfest.xml

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

Entre ellos BLUETOOTHestán los permisos normales de Bluetooth.Si necesita operar Bluetooth, necesita los permisos avanzados de Bluetooth BLUETOOTH_ADMIN, porque estos dos permisos son permisos comunes y solo necesitan agregarse estáticamente, y los dos permisos restantes son permisos peligrosos que necesitan agregarse dinámicamente.

2. Agregar permisos dinámicamente

Primero, determine si AndroidMainfest.xmlel permiso se ha agregado estáticamente en el archivo. Si se ha agregado, puede continuar añadiéndolo dinámicamente, de lo contrario no puede agregarlo dinámicamente.
Agregar estáticamente primero (plantilla)

<uses-permission android:name="android.permission.上表的权限字符" />

Luego agregue dinámicamente (plantilla)

public void requestPower() {
    
    
    //判断是否已经赋予权限
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.上表权限字符)
                != PackageManager.PERMISSION_GRANTED) {
    
    
           //如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.上表权限字符)) {
    
    //这里可以写个对话框之类的项向用户解释为什么要申请权限,并在对话框的确认键后续再次申请权限.它在用户选择"不再询问"的情况下返回false
            } else {
    
    
            //申请权限,字符串数组内是一个或多个要申请的权限,1是申请权限结果的返回参数,在onRequestPermissionsResult可以得知申请结果
                ActivityCompat.requestPermissions(this,
                        new String[]{
    
    Manifest.permission.上表权限字符,}, 1);
            }
        }
    }

Tenga en cuenta que debido a la declaración de juicio, de hecho, cuando el usuario rechaza una solicitud de permiso y vuelve a llamar al método, el cuadro de diálogo de la solicitud de permiso no volverá a aparecer.

3. El método de permiso de aplicación dinámico utilizado en este artículo

Agregar estáticamente primero

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

Luego agregue dinámicamente

public void requestPower() {
    
    
    //判断是否已经赋予权限
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    
    
        //如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
    
    
            //这里可以写个对话框之类的项向用户解释为什么要申请权限,并在对话框的确认键后续再次申请权限.它在用户选择"不再询问"的情况下返回false
        } else {
    
    
            //申请权限,字符串数组内是一个或多个要申请的权限,1是申请权限结果的返回参数,在onRequestPermissionsResult可以得知申请结果
            ActivityCompat.requestPermissions(this, new String[]{
    
    Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        }
    }
}

Nota: aquí, el método para obtener permisos dinámicos está encapsulado en un método, que debe llamarse en onCreatel método para obtener permisos.

4. Interfaz de inicialización

En la primera interfaz, hay tres botones (encender Bluetooth, apagar Bluetooth, escanear Bluetooth) y un Spinnercontrol (usado para mostrar los dispositivos Bluetooth escaneados), inicialícelo y configure el evento de clic correspondiente, vea el código:

private final static String TAG = "hello";
private Button btn_Search, btn_On, btn_Off;
private Spinner mSpinner;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private BluetoothLeScanner bluetoothLeScanner;

//初始化界面
public void initView() {
    
    

    bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
    bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

    btn_Search = findViewById(R.id.btn_Search);		//扫描蓝牙按钮
    btn_On = findViewById(R.id.btn_On);				//开启蓝牙按钮
    btn_Off = findViewById(R.id.btn_Off);			//关闭蓝牙按钮
    mSpinner = findViewById(R.id.spinner);			//显示蓝牙设备的Spinne控件

    btn_Search.setOnClickListener(this);
    btn_On.setOnClickListener(this);
    btn_Off.setOnClickListener(this);
}

El código anterior completa la inicialización de los controles en la primera interfaz y establece el evento de clic, parte del código:

private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private BluetoothLeScanner bluetoothLeScanner;

bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

Es para completar la apertura, cierre y escaneo de Bluetooth, que se presentará en detalle a continuación.

5. Encienda BLE bluetooth

Después de agregar varios permisos, el siguiente paso es operar el bluetooth BLE. Primero, debe abrir el bluetooth cuando abra la aplicación. Primero, agregue el código:

private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();

Primero defina los objetos de BluetoothManager la clase (administrador de Bluetooth) y BluetoothAdapterla clase (adaptador de Bluetooth). El objeto se obtiene bluetoothManagera través del método y el objeto se obtiene a través del método. Si el dispositivo es compatible con Bluetooth, no lo , de lo contrario, lo es . A continuación, puede activar Bluetooth y cargar el códigogetSystemService(Context.BLUETOOTH_SERVICE)bluetoothAdapterbluetoothManager.getAdapter()bluetoothAdapternullnull

public void turnOnBle() {
    
    
    if (bluetoothAdapter != null) {
    
    
        if (bluetoothAdapter.isEnabled() == false) {
    
    
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 11);
        } else {
    
    
            Toast.makeText(this, "蓝牙已经打开了", Toast.LENGTH_SHORT).show();
        }
    } else {
    
    
        Toast.makeText(this, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show();
    }
}

Primero juzgue bluetoothAdapterque no debe nullcontinuar funcionando, de lo contrario, significa que el dispositivo no es compatible con Bluetooth, y luego use bluetoothAdapter.isEnabled()el método para juzgar el estado actual de Bluetooth del dispositivo, si responde que sí, truesignifica que el Bluetooth actual del dispositivo el dispositivo está encendido y pasa Toast(ventana emergente) Solicite al usuario, si el retorno es sí false, significa que el Bluetooth actual del dispositivo está apagado, y luego Intentencienda el Bluetooth a través del método, primero cree un Intentobjeto, y luego use startActivityForResult(intent, 11)el método intentpara transferir, en el que el primer parámetro es Intentun objeto de clase, y el segundo es Uno Codepuede definirlo usted mismo, y luego puede juzgar si el Bluetooth se activó correctamente en la función de devolución de llamada. el código de este método de devolución de llamada no está escrito.Si está interesado, puede implementarlo usted mismo.

6. Desactiva Bluetooth

Después de encender el dispositivo Bluetooth, también podemos completar manualmente la operación de apagar el Bluetooth, primero mire el código

public void turnOffBle() {
    
    
        if (bluetoothAdapter.isEnabled()) {
    
    
            bluetoothAdapter.disable();
        } else {
    
    
            Toast.makeText(this, "蓝牙已经关闭了", Toast.LENGTH_SHORT).show();
        }
    }

En primer lugar, bluetoothAdapter.isEnabled()el estado actual de Bluetooth se obtiene a través del método, y solo cuando el Bluetooth está encendido, bluetoothAdapter.disable()se realiza la operación de apagado y el método se usa para apagar el Bluetooth; de lo contrario, se le solicita al usuario que el Bluetooth actual está apagado, y no hay necesidad de apagar la operación.

7. Escanear Bluetooth

Comience a buscar el código
Después de completar la operación de encendido y apagado de Bluetooth, el siguiente paso es realizar la operación de obtención de los dispositivos Bluetooth circundantes, es decir, el escaneo de Bluetooth. Al principio quería usarloBluetoothAdapter.startLeScan(BluetoothAdapter.LeScanCallback)para escanear, pero descubrí que el indicador de este método está desactualizado y no se recomienda usarlo. Más tarde, después de consultar la información, descubrí que se recomienda usarlo para escanearBluetoothLeScanner.startScan(ScanCallback). Primero veamos el código:

private Handler mHanler = new Handler();
private BluetoothLeScanner bluetoothLeScanner;
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();

//开启蓝牙扫描
public void searchBle() {
    
    
    if (bluetoothAdapter.isEnabled()) {
    
    
        mHanler.postDelayed(myRunnable, 5000);
        btn_Search.setText("停止搜索");
        bluetoothLeScanner.startScan(scanCallback);
    } else {
    
    
        Toast.makeText(MainActivity.this, "请打开蓝牙", Toast.LENGTH_SHORT).show();
    }

}

//延时停止搜索线程
Runnable myRunnable = new Runnable() {
    
    
    @Override
    public void run() {
    
    
        bluetoothLeScanner.stopScan(scanCallback);
        btn_Search.setText("搜索设备");
        setBLESpinner();
    }
};

Antes de comenzar a escanear, debe obtener un objeto de una clase y luego inicializarlo BluetoothLeScanneren la función de inicialización y luego realizar la operación de escanear Bluetooth. En el código para habilitar el escaneo de Bluetooth, el primer paso es juzgar el estado actual de Bluetooth. Si devuelve sí, significa que el Bluetooth actual no está activado, lo que solicita al usuario que active Bluetooth; si devuelve verdadero, entonces Encienda el escaneo de Bluetooth.El subproceso asíncrono en ese momento, es decir, para ejecutar el escaneo de apagar Bluetooth , donde el parámetro es la función de devolución de llamada del escaneo de Bluetooth, y registrar el dispositivo escaneado en la función de devolución de llamada, que se presentará en detalle a continuación. Luego encienda el escaneo de bluetooth y configure el texto del botón escanear bluetooth para "dejar de buscar" , escanear durante 5 segundos, detener el escaneo después de que se acabe el tiempo y configurar el texto del botón escanear bluetooth para "buscar dispositivos" , aquí cambie el texto del botón El propósito es que cuando el usuario haga clic en el botón, se seleccionen diferentes funciones de acuerdo con el texto del botón. Si el texto que se muestra es "buscar dispositivo", la función se ejecuta para buscar, y si el texto visualizado es "detener búsqueda", la función se ejecuta para detener la búsqueda.Se describirá en detalle a continuación. La función del código para detener la búsqueda es actualizar el contenido del control, es decir, mostrar los dispositivos encontrados.bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner()
bluetoothAdapter.isEnabled()falsemHanler.postDelayed(myRunnable, 5000)bluetoothLeScanner.stopScan(scanCallback)scanCallback
bluetoothLeScanner.startScan(scanCallback)btn_Search.setText("停止搜索")searchBle()disSearchBle()
setBLESpinner()Spinner

Detener búsqueda y código de función de devolución de llamada

private List<BluetoothDevice> listdevices = new ArrayList<BluetoothDevice>();	//存放扫描到的设备
private List<String> listdevicename = new ArrayList<String>();					//存放扫描到的设备名字

//停止搜索
public void disSearchBle() {
    
    
    if (bluetoothLeScanner != null) {
    
    
        mHanler.removeCallbacks(myRunnable);
        bluetoothLeScanner.stopScan(scanCallback);
        btn_Search.setText("搜索设备");
        setBLESpinner();
    }

}

//扫描蓝牙设备的回调
public ScanCallback scanCallback = new ScanCallback() {
    
    
    @Override
    public void onScanResult(int callbackType, final ScanResult result) {
    
    
        runOnUiThread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                BluetoothDevice device = result.getDevice();
                String str = device.getName();
                if ((listdevicename.indexOf(str) == -1) && (device.getName() != null)) {
    
    
                    listdevices.add(device);
                    listdevicename.add(str);
                    Log.i(TAG, str);
                }
            }
        });
    }
    @Override
    public void onBatchScanResults(List<ScanResult> results) {
    
    
        super.onBatchScanResults(results);
    }

    @Override
    public void onScanFailed(int errorCode) {
    
    
        super.onScanFailed(errorCode);
    }
};

El código anterior es la función de devolución de llamada para detener el escaneo y el escaneo de Bluetooth. En lo anterior, configuramos que cuando el usuario haga clic en el botón de búsqueda de dispositivos, la búsqueda se detendrá después de 5 segundos. Aquí agregamos la función de implementación de detener la búsqueda. Durante el proceso de búsqueda, el usuario puede hacer clic en el botón para detener la búsqueda (es el mismo botón que el dispositivo de búsqueda, pero el texto que se muestra es diferente) para detener el dispositivo de búsqueda. Cuando se hace clic en este botón, el hilo que se ejecutó después de 5 segundos que configuramos antes se ejecuta primero, y luego la mHanler.removeCallbacks(myRunnable)ejecución bluetoothLeScanner.stopScan(scanCallback)detiene Buscar, ejecutar btn_Search.setText("搜索设备")para configurar el texto mostrado del botón en "buscar dispositivo" y finalmente ejecutar para setBLESpinner()actualizar Spinnerel contenido del control.
En la función de devolución de llamada de escaneo Bluetooth, cuando el dispositivo está buscando dispositivos Bluetooth, el método se ejecutará cada vez que se encuentre un dispositivo. En este método, primero se obtiene el dispositivo escaneado y se obtiene el nombre del dispositivo, y public void onScanResult(int callbackType, final ScanResult result)luego se juzga si el nombre es Para null, si se ha guardado, si no se cumplen las dos condiciones anteriores, el dispositivo se almacenará en la listdevicenamecolección y el nombre del dispositivo se almacenará en listdevicenamela colección.Estas dos colecciones son variables globales, y se usarán más adelante en setBLESpinner()Usado en el método para mostrar los dispositivos escaneados.

8. Mostrar los dispositivos Bluetooth escaneados

En este artículo, los dispositivos Bluetooth escaneados se Spinnermuestran en un control. En el anterior, hemos obtenido los nombres y dispositivos de los dispositivos Bluetooth circundantes, que se almacenan en dos colecciones. El código es el siguiente:

private Spinner mSpinner;
private ArrayAdapter<String> ListAdapter;

mSpinner = findViewById(R.id.spinner);			//显示蓝牙设备的Spinne控件

//将扫描到的设备添加到Spinner控件中
public void setBLESpinner() {
    
    
    mSpinner.setOnItemSelectedListener(this);
    ListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, listdevicename);
    ListAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    mSpinner.setAdapter(ListAdapter);

}

Primero, Spinnerseleccione el monitor para cada elemento en el control. Cuando se selecciona uno de los elementos, el nombre y la dirección del dispositivo Bluetooth pasarán Intenta la segunda interfaz para realizar la conexión, la transmisión de datos, etc. Esto se hará a continuación. Explicación detallada. Luego, listdevicenamecoloque el nombre del dispositivo Bluetooth almacenado en Spinnerel control en el control para mostrarlo, pero no se puede colocar directamente, y un ArrayAdapterobjeto de una clase debe cambiarse en el medio para mostrarse normalmente.

9. Seleccione el dispositivo Bluetooth que se conectará

Una vez completada la pantalla, podemos elegir el dispositivo Bluetooth que necesitamos conectar, primero mire el código:

public static String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

//选择蓝牙设备
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    
    

    String Item = parent.getSelectedItem().toString();
    if (Item != "<BLE List>") {
    
    
        for (BluetoothDevice device : listdevices) {
    
    
            if (Item.equals(device.getName())) {
    
    
                Intent intent = new Intent(this, BLECommunicationActivity.class);
                intent.putExtra(EXTRAS_DEVICE_NAME, device.getName());
                intent.putExtra(EXTRAS_DEVICE_ADDRESS, device.getAddress());
                startActivity(intent);
            }
        }
    }
}

@Override
public void onNothingSelected(AdapterView<?> parent) {
    
    

}

En lo anterior, mSpinner.setOnItemSelectedListener(this)configuramos el evento de escucha seleccionado. Cuando seleccionamos un dispositivo Bluetooth, ejecutaremos el código anterior. Primero, obtendremos Itemel nombre del dispositivo Bluetooth que seleccionamos. Si no es la cadena que agregamos “<BLE List>”, entonces comience atravesando nuestro guardado anterior.El conjunto de dispositivos bluetooth escaneados, encuentre el dispositivo bluetooth correspondiente de acuerdo con el nombre, luego pase el nombre y la dirección del dispositivo a la segunda interfaz, y salte a la segunda interfaz para operaciones posteriores.

10. Evento de oyente de clic de botón

El siguiente es el código para el evento de escucha de clic de botón:

@Override
public void onClick(View v) {
    
    
    switch (v.getId()) {
    
    
        case R.id.btn_On:		//打开蓝牙按钮
            turnOnBle();
            break;
        case R.id.btn_Off:		//关闭蓝牙按钮
            turnOffBle();
            break;
        case R.id.btn_Search:	//搜索蓝牙设备按钮
            if (btn_Search.getText().equals("搜索设备")) {
    
    
            	listdevices.clear();
                listdevicename.clear();
                listdevicename.add("<BLE List>");
                searchBle();
            } else if (btn_Search.getText().equals("停止搜索")) {
    
    
                disSearchBle();
            }
            break;
    }
}

Al hacer clic en el botón Buscar dispositivo Bluetooth, juzgará el texto que se muestra en el botón y ejecutará el método correspondiente de acuerdo con los diferentes textos, entre los cuales

listdevices.clear();
istdevicename.clear();
listdevicename.add("<BLE List>");

La función de estas dos líneas de código es borrar las dos colecciones de dispositivos Bluetooth y nombres antes de que cada dispositivo busque, y almacenar dispositivos y nombres recién escaneados. Dado que Spinnerel control seleccionará automáticamente el contenido del primer elemento, para evitar errores de conexión, usamos listdevicename.add("<BLE List>")esta declaración para garantizar que el primer elemento en la colección de nombres de dispositivos Bluetooth almacenados después de cada exploración sea una cadena definida por nosotros mismos, y luego en el public void onItemSelected(AdapterView<?> parent, View view, int position, long id)método En él, se juzga si la cadena seleccionada es nuestra cadena personalizada, y si no lo es, saltará y se conectará.

Este es el código en la primera interfaz, que solo realiza parte de las funciones. Las siguientes funciones se explicarán en todo el proceso de configuración de Android BLE Bluetooth (2) con el código fuente de la aplicación . Si es necesario, vaya a verificarlo. Si tiene alguna pregunta, puede dejarme un mensaje o un mensaje privado, y le responderé a tiempo cuando lo vea. Si el contenido anterior es incorrecto, no dude en aclararme. Aquí, le deseo éxito en sus estudios. y un futuro brillante~

Cómo obtener el código fuente de Android BLE Bluetooth (HC-08) gratis
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_44355077/article/details/115426863
Recomendado
Clasificación