I'm writing a bluetooth HID server for a small and very simple bluetooth remote. I'm following the documentation here.
My application's permission include:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
And this is my BluetoothServerSocket reading connection-accepting thread:
private class AcceptThread extends Thread {
public void run() {
BluetoothSocket socket = null;
while(true) {
try {
socket = MyBluetoothServerSocket.accept(); // problematic line
} catch(IOException e) {
Log.i(BLUETOOTH_SERVICE, e.toString());
break;
}
if(socket != null) {
readInput(socket);
try {
MyBluetoothServerSocket.close();
} catch (IOException e) {
Log.i(BLUETOOTH_SERVICE, e.toString());
}
} else {
Log.i(BLUETOOTH_SERVICE, "Could not accept a connection from the socket.\n");
}
break;
}
}
}
MyBluetoothServerSocket is a socket constructed like this:
MyBluetoothAdapter.listenUsingRfcommWithServiceRecord("MyService", UUID.fromString("00001124-0000-1000-8000-00805f9b34fb"));
The UUID I'm using above is the only one my remote control device reports through the following method:
MyBluetoothDevice.getUuids();
And MyBluetoothAdapter is just the default adapter:
BluetoothAdapter.getDefaultAdapter();
The rest of the code involved is minimal (making sure bluetooth is on, selecting the correct device) and working correctly. The remote is bonded to the phone.
The line marked as problematic in the code above (accept()) never returns i.e. it blocks forever. What am I doing wrong?
edit: I've tried MyBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord without success.
HID is based on the L2CAP bluetooth profile (protocol?), which is not implemented (line 107) in Android as of October 2013.
This makes it currently impossible to connect to a HID device.
Related
So i got my ESP32 and wanted to do some Porjects and I want to control them with an Android App, for example LED Stripes. I already did this with my Raspberry Pi where it runs perfectly.
I already tried some codes and it could connect to the Wifi. And my PC and even Raspberry Pi could connect to it but when i tried with my Smartphone i just didn't worked.
Here' my Android Code:
mainActivity.jre
connectButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!IPAddress.getText().equals("") || IPAddress.getText() != null || !portNumber.getText().equals("") || portNumber.getText() != null){
return;
}
IPaddresse= IPAddress.getText().toString();
port=Integer.parseInt(portNumber.getText().toString());
try {
client = new Socket(IPaddresse,port);
pw = new PrintWriter(client.getOutputStream());
dataOutputStream= new DataOutputStream(client.getOutputStream());
msg.setText("Verbunden!");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Permissions:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
ESP32 Code:
#include <WiFi.h>
const char* ssid="Name";
const char* password="password";
WiFiServer server(80 );
void setup() {
Serial.begin(115200);
Serial.println("start");
delay(1000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
Serial.println(WiFi.localIP());
server.begin();
}
void loop() {
WiFiClient client = server.available();
if (client) {
while (client.connected()) {
while (client.available()>0) {
char c = client.read();
client.write(c);
}
Serial.println(client.localIP());
delay(10);
}
}
}
Sorry for my English. And my Code isn't the best im just beginning to Code
Thanks
First on the ESP32 i suggest you add mDNS to your setup, this allows you to give your esp a name on the network like when you give your esp the name pietje then you can find it as pietje.local on your network.
This seems not to work properly with the socket class, but maybe i did something work. It did not finding the ip of it. It was the first time working with sockets. So i learned something new.
I tried your example and it did fault me to. With some short search i found this website:
https://www.tutorialspoint.com/sending-and-receiving-data-with-sockets-in-android
By adding you socket creation inside a thread it did work for me.
I hope this helps you ahead.
I am able to pair devices with the android studio app but I get the tag
"CouldNotConnectToSocket" even though the device is paired.
I am new to android studio so I am really stuck with where to go next.
I also get
getBluetoothService() called with no BluetoothManagerCallback
The UUID I created is:
private final static UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Can anyone please help me?
new Thread() {
#Override
public void run() {
device = BA.getRemoteDevice(address);
try {
BTSocket = device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//BTSocket = createBluetoothSocket(device);
Log.d(TAG, "Device Connected");
BA.cancelDiscovery();
BTSocket.connect();
} catch (IOException ex) {
Log.d(TAG, "CouldNotConnectToSocket");
closeSocket(BTSocket);
}
}
}.start();
The issue I found out was that the devices I was trying to connect to send data back and forth require Bluetooth Low Energy support from the app.
I'm trying to use an Android device to connect to Bluetooth devices to retrieve some information. In particular I'm trying to connect to Bluetooth headphones on this UUID:
"0000111E-0000-1000-8000-00805F9B34FB"
To do this I'm creating a socket and connecting it to the remote device this way:
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket
// because mmSocket is final.
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothSocket tmp = null;
mmDevice = device;
try {
// Get a BluetoothSocket to connect with the given BluetoothDevice.
// MY_UUID is the app's UUID string, also used in the server code.
tmp = device.createRfcommSocketToServiceRecord(UUID_HF);
} catch (IOException e) {
Log.e(TAG, "Socket's create() method failed", e);
}
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it otherwise slows down the connection.
bluetoothAdapter.cancelDiscovery();
try {
// Connect to the remote device through the socket. This call blocks
// until it succeeds or throws an exception.
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and return.
try {
mmSocket.close();
} catch (IOException closeException) {
Log.e(TAG, "Could not close the client socket", closeException);
}
return;
}
// The connection attempt succeeded. Perform work associated with
// the connection in a separate thread.
manageMyConnectedSocket(mmSocket);}
It works fine when the headphones are not yet connected with my Android device. But what happens is that the headphones connect automatically with my Android device thanks to the OS itself. And in this case, when I execute the mmSocket.connect() method, it does not return. I thought that maybe Android has connected automatically another socket with the same UUID and so mine doesn't work. Do you think this is the problem? And if it is, is there a way to close all the sockets between my Android device and a remote Bluetooth device? Or maybe just the one that is bothering my process?
Thanks in advance.
what actually happens is the OS is doing the paired device criteria to save some battery as the searching process consume a lot of energy.
since you've done the search you should go for searching in paired devices not normal search and the result of the search should be taken from
Query paired devices
Before performing device discovery, it's worth querying the set of paired devices to see if the desired device is already known. To do so, call getBondedDevices(). This returns a set of BluetoothDevice objects representing paired devices. For example, you can query all paired devices and get the name and MAC address of each device, as the following code snippet demonstrates:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
// There are paired devices. Get the name and address of each paired device.
for (BluetoothDevice device : pairedDevices) {
String deviceName = device.getName();
String deviceHardwareAddress = device.getAddress(); // MAC address
}
}
To initiate a connection with a Bluetooth device, all that's needed from the associated BluetoothDevice object is the MAC address, which you retrieve by calling getAddress(). You can learn more about creating a connection in the section about Connecting Devices.
this is the official documentation from google covering every detail about Bluetooth:
https://developer.android.com/guide/topics/connectivity/bluetooth
I recently tried to port my application that requires receiving (udp) broadcast messages. My udp receiving code works on pc (windows/linux), but with android there seems to be some problem receiving broadcast messages, however, i seem to be able to send broadcast messages with android and receive acknowledgment packet from pc version.
Tried to find solution but anything close to the answer is that it MIGHT not work on my device and there was really any info on how i can be sure that this is the case, so felt that there should be thread for making sure it is indeed hardware/firmware problem and not problem in my code, like if there is something android specific that i forgot to enable? Tested with galaxy S (kitkat) and Galaxy s3 mini (kitkat) and both have same problem
(under onCreate)
WifiManager wifi;
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock wifilock = wifi.createMulticastLock("compvter.qft");
Log.i("wifilock", "multicastLock.isHeld() = " +wifilock.isHeld());
Log.i("wifilock", "multicastLock.toString() = " +wifilock.toString());
wifilock.acquire();
Log.i("wifilock", "multicastLock.isHeld() = " + wifilock.isHeld());
Log.i("wifilock", "multicastLock.toString() = " + wifilock.toString());
if (Settings.socket==null)
{
initsocket();
}
UdpServer udpserver = new UdpServer();
udpserver.start();
Under udpserver class
public volatile boolean keepServerRunning=true;
public void run()
{
boolean none=true;
try {
byte[] buffer = new byte[Settings.udppacketsize];
while (keepServerRunning==true)
{
DatagramPacket inpacket = new DatagramPacket(buffer,buffer.length);
Settings.socket.setSoTimeout(1000);
try
{
Settings.socket.receive(inpacket);
none=false;
}
catch (SocketTimeoutException e)
{
none=true;
}
if (none==false)
{
handler handler = new handler(Settings.socket, inpacket);
handler.start();
}
}
Settings.socket.close();
} catch (IOException e)
{
}
}
Logging for wifilock gives:
02-01 16:34:07.516 17365-17365/com.test.oappi.qft I/Wifilock﹕ multicastLock.isHeld() = false
02-01 16:34:07.516 17365-17365/com.test.oappi.qft I/wifilock﹕ multicastLock.toString() = MulticastLock{ 425b3ff8; refcounted: refcount = 0 }
02-01 16:34:07.516 17365-17365/com.test.oappi.qft I/wifilock﹕ multicastLock.isHeld() = true
02-01 16:34:07.516 17365-17365/com.test.oappi.qft I/wifilock﹕ multicastLock.toString() = MulticastLock{ 425b3ff8; held; refcounted: refcount = 1 }
Manifest permissions
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
Since the wifi state definitely changes, does this mean that i really have two android phones unable to receive broadcast messages or does API version i try to develop matter since i am trying to develop to Api lvl 10. If someone has idea how to check devices broadcast receiving capability please tell it.
I am trying to create a Java Client-Server Program, where the Server is running on a Windows PC, and the Client is running on an Android 2.2 Phone.
The Connection is okay. Sending Data from the Phone to the PC works also fine.
Just receiving Data on the Phone crashes the program.
I am using DataInputStream and DataOutputStream to read/write through the Socket.
//Thread on the Phone
public void run() {
while (RUN) {
if (socket != null && socket.isConnected()) {
try {
//Crash
String text = dis.readUTF();
myTextView.setText(text);
} catch (IOException ex) {
//ErrorHandling
}
}
}
}
I want to receive a String from the server and then show it in a TextView.
Any Ideas? I am already setting this permission:
<uses-permission android:name="android.permission.INTERNET" />
do i need any other permissions? Thanks.
you can't set text on your UI if you're not in the UI thread.
do this...
add:
Runnable showmessage = new Runnable() {
public void run() {
myTextView.setText(membervariabletext);
}
};
and from your thread, after the readUTF(), call "runOnUiThread(showmessage);"
I would ensure that your Data Input Stream is initiated correctly:
Socket s = new Socket(serverAddress, port);
DataInputStream dis = new DataInputStream(s.getInputStream());
Otherwise, here's a link for example code where someone uses InputStreamReader() and OutputStreamWriter() to make a server and client for Android.
https://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/