java - manejo - Enviar una cadena a través de Bluetooth desde una PC como cliente a un móvil como servidor
manejo de cadenas en java (2)
Necesito ayuda transfiriendo una cadena desde una PC a un dispositivo móvil Android a través de Bluetooth. El dispositivo móvil Android debe actuar como un servidor y muestra el mensaje de cadena en la pantalla del dispositivo. La PC que es el cliente debe enviar la cadena al dispositivo móvil.
Quiero que el servidor reaccione en la cadena extraída (transferida a través de Bluetooth). Eso significa que, por un lado, el servidor siempre tiene que escuchar nuevas cadenas para que lleguen, pero en el otro lado todavía tiene que poder reaccionar ante estos mensajes (por ejemplo, navegar de un menú a otro).
Lo probé usando BlueCove (2.1.1) como BluetoothStack (para el que agrego el jar de BlueCove como biblioteca a ambos proyectos) en combinación con un ejemplo de comunicación servidor-cliente que encontré here .
Actualizaciones:
Código actualizado del servidor gracias a user_CC utilizando una conexión RFComm
para el servidor:
public class RFCommServer extends Thread{
//based on java.util.UUID
private static UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");
// The local server socket
private BluetoothServerSocket mmServerSocket;
// based on android.bluetooth.BluetoothAdapter
private BluetoothAdapter mAdapter;
private BluetoothDevice remoteDevice;
private Activity activity;
public RFCommServer(Activity activity) {
this.activity = activity;
}
public void run() {
BluetoothSocket socket = null;
mAdapter = BluetoothAdapter.getDefaultAdapter();
// Listen to the server socket if we''re not connected
while (true) {
try {
// Create a new listening server socket
Log.d(this.getName(), ".....Initializing RFCOMM SERVER....");
// MY_UUID is the UUID you want to use for communication
mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord("MyService", MY_UUID);
//mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); // you can also try using In Secure connection...
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (Exception e) {
}
try {
Log.d(this.getName(), "Closing Server Socket.....");
mmServerSocket.close();
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
DataInputStream mmInStream = new DataInputStream(tmpIn);
DataOutputStream mmOutStream = new DataOutputStream(tmpOut);
// here you can use the Input Stream to take the string from the client whoever is connecting
//similarly use the output stream to send the data to the client
RelativeLayout layout = (RelativeLayout) activity.findViewById(R.id.relativeLayout_Layout);
TextView text = (TextView) layout.findViewById(R.id.textView_Text);
text.setText(mmInStream.toString());
} catch (Exception e) {
//catch your exception here
}
}
}
Código del cliente SPP desde here :
/**
* A simple SPP client that connects with an SPP server
*/
public class SampleSPPClient implements DiscoveryListener{
//object used for waiting
private static Object lock=new Object();
//vector containing the devices discovered
private static Vector vecDevices=new Vector();
private static String connectionURL=null;
public static void main(String[] args) throws IOException {
SampleSPPClient client=new SampleSPPClient();
//display local device address and name
LocalDevice localDevice = LocalDevice.getLocalDevice();
System.out.println("Address: "+localDevice.getBluetoothAddress());
System.out.println("Name: "+localDevice.getFriendlyName());
//find devices
DiscoveryAgent agent = localDevice.getDiscoveryAgent();
System.out.println("Starting device inquiry...");
agent.startInquiry(DiscoveryAgent.GIAC, client);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Device Inquiry Completed. ");
//print all devices in vecDevices
int deviceCount=vecDevices.size();
if(deviceCount <= 0){
System.out.println("No Devices Found .");
System.exit(0);
}
else{
//print bluetooth device addresses and names in the format [ No. address (name) ]
System.out.println("Bluetooth Devices: ");
for (int i = 0; i <deviceCount; i++) {
RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
System.out.println((i+1)+". "+remoteDevice.getBluetoothAddress()+" ("+remoteDevice.getFriendlyName(true)+")");
}
}
System.out.print("Choose Device index: ");
BufferedReader bReader=new BufferedReader(new InputStreamReader(System.in));
String chosenIndex=bReader.readLine();
int index=Integer.parseInt(chosenIndex.trim());
//check for spp service
RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(index-1);
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID("446118f08b1e11e29e960800200c9a66", false);
System.out.println("/nSearching for service...");
agent.searchServices(null,uuidSet,remoteDevice,client);
try {
synchronized(lock){
lock.wait();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
if(connectionURL==null){
System.out.println("Device does not support Simple SPP Service.");
System.exit(0);
}
//connect to the server and send a line of text
StreamConnection streamConnection=(StreamConnection)Connector.open(connectionURL);
//send string
OutputStream outStream=streamConnection.openOutputStream();
PrintWriter pWriter=new PrintWriter(new OutputStreamWriter(outStream));
pWriter.write("Test String from SPP Client/r/n");
pWriter.flush();
//read response
InputStream inStream=streamConnection.openInputStream();
BufferedReader bReader2=new BufferedReader(new InputStreamReader(inStream));
String lineRead=bReader2.readLine();
System.out.println(lineRead);
}//main
//methods of DiscoveryListener
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
//add the device to the vector
if(!vecDevices.contains(btDevice)){
vecDevices.addElement(btDevice);
}
}
//implement this method since services are not being discovered
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
if(servRecord!=null && servRecord.length>0){
connectionURL=servRecord[0].getConnectionURL(0,false);
}
synchronized(lock){
lock.notify();
}
}
//implement this method since services are not being discovered
public void serviceSearchCompleted(int transID, int respCode) {
synchronized(lock){
lock.notify();
}
}
public void inquiryCompleted(int discType) {
synchronized(lock){
lock.notify();
}
}//end method
}
Para las pruebas, uso un Galaxy Nexus (GT-I9250) con la última API de Android.
Gracias a user_CC , el cliente y el servidor ahora se ejecutan sin excepción. Pero, lamentablemente, el cliente no puede conectarse al servidor (consulte la captura de pantalla a continuación). Esto se debe a que el connectionURL
nunca se establece (por lo tanto, salta aquí if(connectionURL==null)
por defecto.
¿Cómo puedo cambiar el código del cliente para poder conectarlo con el servidor? Necesito una connectionURL
adecuada en la siguiente línea:
StreamConnection streamConnection=(StreamConnection)Connector.open(connectionURL)
Hasta ahora solo me enteré de que de alguna manera necesito obtener el ServiceRecord
, lamentablemente esto tampoco se describe en el código de ejemplo de here .
Necesitará utilizar el APIS RFComm para que la comunicación funcione. He logrado definir una clase que es un subproceso y actuará como un servidor y escuchará las conexiones de los clientes. También he puesto algunos comentarios para que los entiendas.
private class AcceptThread extends Thread {
// The local server socket
private BluetoothServerSocket mmServerSocket;
public AcceptThread() {
}
public void run() {
BluetoothSocket socket = null;
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
// Listen to the server socket if we''re not connected
while (true) {
try {
// Create a new listening server socket
Log.d(TAG, ".....Initializing RFCOMM SERVER....");
// MY_UUID is the UUID you want to use for communication
mmServerSocket = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
//mmServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); you can also try using In Secure connection...
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (Exception e) {
}
try {
Log.d(TAG, "Closing Server Socket.....";
mmServerSocket.close();
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
mmInStream = new DataInputStream(tmpIn);
mmOutStream = new DataOutputStream(tmpOut);
// here you can use the Input Stream to take the string from the client whoever is connecting
//similarly use the output stream to send the data to the client
} catch (Exception e) {
//catch your exception here
}
}
}
}
espero que esto ayude
Para tu otra pregunta:
La declaración de javax.bluetoothIDID en la clase UUID del lado del cliente (PC) debe ser de javax.bluetoothIDID
uuidSet2[0] = new UUID("446118f08b1e11e29e960800200c9a66", false);
Declarar java.utilID en el lado del servidor (Android)
UUID MY_UUID = UUID.fromString("446118f0-8b1e-11e2-9e96-0800200c9a66");
No soy un desarrollador de Java pero he tenido un problema similar con Mono para Android (c #)
El UUID para SPP debe ser "00001101-0000-1000-8000-00805F9B34FB"
Este es un UID conocido para identificar un adaptador SPP de Bluetooth.
En mi código c # que parece
private static UUID MY_UUID = UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
Supongo que puedes actualizar tu código Java a algo como:
new UUID("00001101-0000-1000-8000-00805F9B34FB", true);
Aunque no estoy seguro de qué parámetros acepta la función, es posible que tenga que verificar eso.
Estaba usando el dispositivo Android como cliente, pero la información puede serle de utilidad.
así que incluiré mi código c # aquí, que originalmente traduje desde ejemplos de Java,
así que deberías poder traducirlo de vuelta:
btAdapter = BluetoothAdapter.DefaultAdapter;
btAdapter.CancelDiscovery(); //Always call CancelDiscovery before doing anything
remoteDevice = btAdapter.GetRemoteDevice(Settings["deviceaddress"].ToString());
socket = remoteDevice.CreateRfcommSocketToServiceRecord(MY_UUID);
socket.Connect();
Básicamente obtengo el adaptador predeterminado, cancelo cualquier operación de descubrimiento en ejecución y luego creo un socket para el otro dispositivo. En su caso, querrá escuchar en lugar de conectarse, pero solo para su información.
Espero que ayude, lo siento, no pude darle más información específica de Java.
''Actualización:'' Acabo de encontrar una pequeña muestra en Java que más o menos sigue el mismo método que el que estoy usando: ¿ Problemas con la conexión de SPP con Bluetooth en Android?