Spanish BlueTooth

figorra

Member
Licensed User
Longtime User
Además del tutorial que viene en este foro Aqui..., me gustaria iniciar un hilo es ESPAÑOL sobre como configurar, enviar y recibir datos desde el dispositivo a otros dispositivos o pcs.

Se que el hilo en ingles es muy completo, pero a pesar de haberme bajado los ejemplos, estos no me funcionan como deberian, sea por el motivo que sea.

Es por ello que en este hilo me gustaria dejar las BASES de una conexión, las caracteristicas y si es posible (se que podremos) la solución del mismo.
 

figorra

Member
Licensed User
Longtime User
1ª aportación

Según parece ser, en B4A es necesario empezar por habilitar las librerías siguientes:

- Core (marcada por defecto)
- Serial (que no está marcada por defecto)
- RandomAccesFile (que no esta marcada por defecto, esta libreria la usamos para el streaming)

(para los mas novatos, en la parte de abajo a la derecha de B4A hay 4 pestañas, una dice LIB, y allí solo tenemos que marcarlas y se cargan solas)

Es necesario que el dispositivo cuente con Android 2.0 o superior y con API nivel 5 o superior.

Para la pantalla, necesitamos crear los siguientes controles:

- Caja de texto (txtLog) que recogerá los datos recibidos desde el bluetooth.
- Caja de texto (txtSend) que será donde pongamos los datos que queremos enviar.
- Boton (btnSend) Que se encargará de enviar los datos de la caja de texto txtSend.
- Etiqueta LABEL (label1) que nos comunicará que hacer en cada momento.

Despues de haber creado esta pantalla (activity) a la que llamaremos "1", grabamos y hacemos que genere los miembros (generate members) del boton. No serán necesaria más acciones por el momento.

Cerramos el diseñador (da igual si lo hacemos desde el emulador o mediante el puente a nuestro movil BRIDGE, etc....)

Ahora vamos a ver la parte del codigo.

Lo primero que haremos será declarar las Variables:

B4X:
Sub Process_Globals
   Dim Serial1 As Serial
   Dim TextReader1 As TextReader
   Dim TextWriter1 As TextWriter
   Dim Timer1 As Timer
   Dim connected As Boolean
End Sub

Sub Globals
   Dim btnSend As Button
   Dim txtLog As EditText
   Dim txtSend As EditText
End Sub

El Process_Globals para las variables que servirán para toda la aplicacion (es decir para todas las pantallas o activities) nos permitirá mejorar y adaptar este codigo en caso que queramos crear mas pantallas. En este proceso declaramos las variables que nos permitiran trabajar con el puerto serial, los "lectores" y "escritores" que nos permitirar trabajar con streaming (streaming en caso necesario), la variable del temporizador TIMER para que podamos preguntar si hay datos cada cierto tiempo y un FLAG (bandera) que nos dirá si estamos o no conectados.

El Globalsnos dará las variables que solo nos serviran para esta pantalla o activity. Aqui definimos las variables de los objetos que tenemos en pantalla, como las cajas de texto o el boton.

B4X:
Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      Serial1.Initialize("Serial1")
      Timer1.Initialize("Timer1", 200)
   End If
   Activity.LoadLayout("1")
   Activity.AddMenuItem("Conectar", "mnuConnect")
   Activity.AddMenuItem("Desconetar", "mnuDisconnect")
End Sub

Esta rutina se carga al iniciar la pantalla (activity). Tienes la opcion de preguntar si es la primera vez que se abre (FirstTime <TRUE O FALSE> ya que es boolean). Lo primero que hacemos es preguntar si es la primera vez que cargamos esa actividad, y en caso afirmativo inicializamos el puerto y el temporizador a 200 (2 segundos) que sera el tiempo en que el programa pasara por la rutina de ese temporizador. Sea o no la primera vez, le decimos a la pantalla que cargue la plantilla (LoadLayout) y que agrege dos Items (objetos) al menu de la pantalla. Estos objetos se verán cuando pulsemos la opción menú de nuestro telefono movil, es decir, no sale en la pantalla (activity) principal si no son llamados desde este botón.

B4X:
Sub Activity_Resume
   If Serial1.IsEnabled = False Then
      Msgbox("Active el BlueTooth.", "")
   Else
      Serial1.Listen 
   End If
End Sub

La rutina Activity_Resume (en este caso no se refiere a resumen sino a continuar) se carga una vez se ha cargado la pantalla (activity) y lo que hace es comprobar si nuestro puerto está disponible o no. Si no lo está te dice que actives el bluetooth y si lo está se pone a "escuchar" el puerto.

B4X:
Sub mnuConnect_Click
   Dim PairedDevices As Map
   PairedDevices = Serial1.GetPairedDevices
   Dim l As List
   l.Initialize
   For i = 0 To PairedDevices.Size - 1
      l.Add(PairedDevices.GetKeyAt(i))
   Next
   Dim res As Int
   res = InputList(l, "Seleccione un dispositivo", -1) 
   If res <> DialogResponse.CANCEL Then
      Serial1.Connect(PairedDevices.Get(l.Get(res)))
   End If
End Sub

Esta rutina se carga cuando pulsamos el boton Conectar del menu (si, ese que habia que darle al menu del telefono para que aparezca). Aqui hay varias cosas interesantes.

Lo primero que hace es crear un MAP (mapa) con los dispositivos que estan asociados a nuestro telefono, es decir, antes de iniciar una conexión, es necesario que con las opciones del movil "PAREEMOS" o "EMPAREJAMOS" estos dispositivos para que salgan en esta lista. Es cierto que podríamos usar RATIO, etc... para buscar nuevos, pero para este ejemplo lo emparejaremos antes. GetPairedDevices lo que hace es preguntar a nuestro dispositivos los "nombre" (ya se que no es el nombre en si) de los dispositivos previamente emparejados.

Dim l As List
l.Initialize
For i = 0 To PairedDevices.Size - 1
l.Add(PairedDevices.GetKeyAt(i))
Next

Estas lineas crean una lista que añade los dispositivos que hay vigentes.

Dim res As Int
res = InputList(l, "Seleccione un dispositivo", -1)
If res <> DialogResponse.CANCEL Then
Serial1.Connect(PairedDevices.Get(l.Get(res)))
End If

Y estas lineas lo que hacen es mostrarnos una caja de dialogo con los dispositivos encontrados para que seleccionemos uno de ellos. En caso de no ser cancelada CONECTA con el dispositivo seleccionado.

B4X:
Sub Serial1_Connected (Success As Boolean)
   If Success Then
      ToastMessageShow("Conectado", False)
      TextReader1.Initialize(Serial1.InputStream)
      TextWriter1.Initialize(Serial1.OutputStream)
      Timer1.Enabled = True
      connected = True
   Else
      connected = False
      Timer1.Enabled = False
      Msgbox(LastException.Message, "Error de conexion.")
   End If
End Sub

En el momento de conectar, salta esta rutina, a la cual se le puede preguntar si ha tenido exito (success) o no. En caso de no tener exito, desactiva el temporizador, pone la variable flag a falso y muestra el mensaje de error. En caso de conexión lanza un mensaje de conectado e inicializa los "lectores" y "escritores" de datos, uno como entrante y otro como saliente. Habilita el temporizador y pone la variable flag a verdadero.

B4X:
Sub mnuDisconnect_Click
   Serial1.Disconnect
   connected = False
End Sub

Esta rutina se activa cuando se hace clic en Desconectar del boton del menú. Desconecta el puerto serie y la variable flag se pone a falso.

B4X:
Sub btnSend_Click
   If connected Then
      TextWriter1.WriteLine(txtSend.Text)
      TextWriter1.Flush
      txtSend.Text = ""
   End If
End Sub

Esta rutina se lanza al hacer clic en el boton enviar. Pregunta si la variable flag es verdadera y escribe en el "escritor" del streaming, "levanta" el "escritor" para que cumpla con su cometido y borra la caja de texto para dejarla libre.

B4X:
Sub Timer1_Tick
   If connected Then
      If TextReader1.Ready Then
         txtLog.Text = txtLog.Text & TextReader1.ReadLine & CRLF
         txtLog.SelectionStart = txtLog.Text.Length
      End If
   End If
End Sub

Esta es la rutina del timer, la cual se lanza (en nuestro caso--> mirar mas arriba) cada 2 segundos. Si esta conectado según nuestra variable flag, y si la "lector" del streaming esta disponible, escribe el contenido en la caja de texto y se posiciona al final del mismo despues del retorno de carro.

Este es todo el codigo, no hay mas.........
 

figorra

Member
Licensed User
Longtime User
Pues bien amigos, a pesar de que como veis entiendo el codigo arriba indicado, se me lanza el error siguiente:

java.io.ioException: Service Discovery Failed

cuando intento conectar con otro dispositivo (otro movil) y no se que estoy haciendo mal.

Con otros ejemplos del foro me pasa igual.

Mi movil es un LG modelo E610V con android 4.0.3

Alguna idea?
 

Heppy

Active Member
Licensed User
Longtime User
Buen trabajo figorra.

Yo no lo hago así.
A mi me funciona bien de esta forma.
No se si es funcional este código (en el link de abajo hay un ejemplo funcional), por que tengo una parte en el activity (buscar dispositivos que guardo la MAC del que quiero conectar) y un servicio para que no se detenga la aplicación que es donde trato el BTSerial.
Luego utilizo también una librería que se llama BTAutoPair que por medio de un broadcast intercepta el mensaje de la contraseña bluetooth y puedes poner directamente por código la tuya.

El post es este:
http://www.b4x.com/android/forum/th...matic-bluetooth-device-bonding.25675/#content


B4X:
Sub Process_Globals
   Dim admin As BluetoothAdmin   Dim Dispositivos As List
   Type NameAndMac (Name As String, Mac As String)
   Dim connectedDevice As NameAndMac
   Dim BtSerial As Serial
   Dim AStreams As AsyncStreams
End Sub

Sub Buscar_click
   Dispositivos.Initialize
   If admin.StartDiscovery   = False Then
     ToastMessageShow("Error starting discovery process.", True)
   Else
     ProgressDialogShow("Searching for devices...")
   End If
End Sub

Sub admin_DeviceFound (Name As String, MacAddress As String)
   'Log(Name & ":" & MacAddress)
   Dim nm As NameAndMac
   nm.Name = Name
   nm.Mac = MacAddress
   Dispositivos.Add(nm)
   ProgressDialogShow("Buscando Bluetooths (~ Dispositivo encontrado)...".Replace("~", Dispositivos.Size))
End Sub

Sub admin_DiscoveryFinished
   ProgressDialogHide
   If Dispositivos.Size = 0 Then
     ToastMessageShow("No hay dispositivos.", True)
   Else
     Dim l As List
     l.Initialize     For i = 0 To Dispositivos.Size - 1
       Dim nm As NameAndMac
       nm = Dispositivos.Get(i)
       l.Add(nm.Name)
     Next
     Dim res As Int
     res = InputList(l, "Elija el dispositivo", -1)
     BtSerial.Connect(L.Get(res))
   End If
End Sub

Sub BtSerial_Connected (Success As Boolean)   ' Event handler
   If (Success=True) Then
     If AStreams.IsInitialized = False Then AStreams.Initialize(BtSerial.InputStream, BtSerial.OutputStream, "Astreams")
     ConectadoB=True
     ToastMessageShow("Conectado",True)
     Log("Connected")
   Else
     ConectadoB=False
     Log("Desconectado")
     ToastMessageShow("Desconectado", True)
   End If
End Sub

Sub AStreams_NewData (Buffer() As Byte)
  Dim msg As String
  msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
'  codigo analisis
end sub

Sub AStreams_Error
  'ToastMessageShow(LastException.Message, True)
'  StartServiceAt("", DateTime.Now + 1 * DateTime.TicksPerMinute, True) 'schedule the next task to run in 30 seconds.
End Sub

Sub AStreams_Terminated
'  ConectadoB=False
End Sub
 

cas6678

Active Member
Licensed User
Longtime User
Yo tambien estoy con problemas con el bluetooth. Bueno mas que problemas intentando entenderlo...

Yo descargue el archivo bluetooth.zip del siguiente link y consegui entablar un chat entre un movil y un tablet android via bluetooth.

http://www.b4x.com/android/forum/threads/android-bluetooth-bluetoothadmin-tutorial.14768/

Parecer ser que ese codigo esta basado en el SerialExample.zip que tu indicas. Este ultimo a mi no me funciono, no se por que, quizas hice algo mal, el otro si, perfecto, pruebalo a ver que pasa o busca las posibles diferencias.
 
Top