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.xml
configurados 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.xml
en , 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_LOCATION
un 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_LOCATION
En este artículo , se utilizan ACCESS_COARSE_LOCATION
permisos peligrosos y permisos normales . Primero, BLUETOOTH
debe agregar permisos de forma estática al archivo:BLUETOOTH_ADMIN
AndroidMainfest.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 BLUETOOTH
está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.xml
el 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 onCreat
el 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 Spinner
control (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 BluetoothAdapter
la clase (adaptador de Bluetooth). El objeto se obtiene bluetoothManager
a 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)
bluetoothAdapter
bluetoothManager.getAdapter()
bluetoothAdapter
null
null
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 bluetoothAdapter
que no debe null
continuar 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í, true
significa 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 Intent
encienda el Bluetooth a través del método, primero cree un Intent
objeto, y luego use startActivityForResult(intent, 11)
el método intent
para transferir, en el que el primer parámetro es Intent
un objeto de clase, y el segundo es Uno Code
puede 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 BluetoothLeScanner
en 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()
false
mHanler.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 Spinner
el 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 listdevicename
colección y el nombre del dispositivo se almacenará en listdevicename
la 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 Spinner
muestran 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, Spinner
seleccione 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 Intent
a la segunda interfaz para realizar la conexión, la transmisión de datos, etc. Esto se hará a continuación. Explicación detallada. Luego, listdevicename
coloque el nombre del dispositivo Bluetooth almacenado en Spinner
el control en el control para mostrarlo, pero no se puede colocar directamente, y un ArrayAdapter
objeto 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 Item
el 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 Spinner
el 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