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.
Related
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.
Here is my registration code:
protected void initializeManagerOpen(){
consoleWrite("initializeOpen");
if(mSipManager==null) {
return;
}
SipProfile.Builder builder;
try {
builder = new SipProfile.Builder("13", "10.0.0.4");
builder.setPassword("13");
builder.setPort(5062);
builder.setProtocol("UDP");
mSipProfile = builder.build();
try {
Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pendingIntent, null);
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
mNotificationTask.endNotification();
mNotificationTask.createNotification(R.drawable.ic_stat_connecting,"Test","Connecting");
consoleWrite("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime){
mNotificationTask.endNotification();
mNotificationTask.createNotification(R.drawable.ic_stat_connected,"Test","Connected");
consoleWrite("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage){
mNotificationTask.endNotification();
mNotificationTask.createNotification(R.drawable.ic_stat_disconnected,"Test","Failed to connect:"+errorCode);
consoleWrite("Registration failed. Please check settings.");
consoleWrite(""+errorCode);
consoleWrite(errorMessage);
}
});
} catch (SipException e) {
e.printStackTrace();
}
} catch (ParseException e) {
e.printStackTrace();
}
}
Though sometimes it registered successfully, most time I got a error code -9:
Registration failed. Please check settings.
-9
0
I found this description on reference site:
public static final int IN_PROGRESS
The client is in a transaction and cannot initiate a new one.
Constant Value: -9 (0xfffffff7)
What does it means exactly? I don't have any other SIP application running on my phone.
PS. First time when i am trying to connect, it is working. But second time it returns -9. Maybe i not close connection correctly? I think i have problem because i am trying to close connection but it is not closing...
public void closeLocalProfile() {
if(mSipManager==null){
return;
}
try{
if(mSipProfile!=null){
mSipManager.close(mSipProfile.getUriString());
consoleWrite("mSipManager Closed - "+mSipProfile.getUriString());
}
}catch(Exception e){
consoleWrite("Failed to close local profile. - "+e);
}
}
Delete all SIP account from Call Parameter and retry :
Call App->Parameter->Call account internet
Delete all account
PS: Sorry for the name menu, my phone isn't in english
I've faced the same issue and zicos22's comment helped me to solve it. The problem starts because of unclosed SipProfiles, so you need to run closeLocalProfile() inside onPause() method (it does not work when called inside onDestroy()). Actually, i think i have to run this sip stuff in separate thread, but for now i'm just closing profile in onPause. On my android phone with ZenUI i'am able to close currently opened sip profiles manually in Settings -> Call Settings -> Phone Account Settings -> SIP accounts.
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.
I usually use this
private void ensureDiscoverable() {
if(D) Log.d(TAG, "ensure discoverable");
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
But that prompts a user confirmation. Is there a way to bypass this programmatically?
Also, I suppose there are no "news" on the "always discoverable mode" ?
After some research I concluded that setting discoverable timeout without user interaction it's only possible with root access (as already suggested in the previous answer). However for someone who need that here is the necessary solution:
private void ensureBluetoothDiscoverability() {
try {
IBluetooth mBtService = getIBluetooth();
Log.d("TESTE", "Ensuring bluetoot is discoverable");
if(mBtService.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Log.e("TESTE", "Device was not in discoverable mode");
try {
mBtService.setDiscoverableTimeout(100);
// mBtService.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, 1000);
} catch(Exception e) {
Log.e("TESTE", "Error setting bt discoverable",e);
}
Log.i("TESTE", "Device must be discoverable");
} else {
Log.e("TESTE", "Device already discoverable");
}
} catch(Exception e) {
Log.e("TESTE", "Error ensuring BT discoverability", e);
}
}
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
And then create a new package android.bluetooth, place two files inside IBluetooth.aidl and IBluetoothCallback.aidl and put inside the code as shown here.
This will allow to access functions that are not available on the standard API, but for some of them you will need permission to "write secure settings" (the comment line above is where you will get that exception for lack of permissions of the process/user).
That's what I did and it works fine for me :
Method :
public void makeDiscoverable (int timeOut){
Class <?> baClass = BluetoothAdapter.class;
Method [] methods = baClass.getDeclaredMethods();
Method mSetScanMode = methods[44];
try {
mSetScanMode.invoke(Util.mBluetoothAdapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, timeOut);
} catch (Exception e) {
Log.e("discoverable", e.getMessage());
}
}
Add permission :
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
Nothing - It still needs user confirmation.
BEing always discoverable is a drain on battery - so there is no easy solution
Also it is a privacy issue.
Its better to ask the user.
After testing and searching for various options, I have created these lines that don't require an user interaction. I hope it helps:
In method:
try{
Method metodo = BluetoothAdapter.class.getMethod("setScanMode", int.class);
try {
metodo.invoke(bluetoothAdaptador, SCAN_MODE_CONNECTABLE_DISCOVERABLE);
}catch (InvocationTargetException e) {
e.printStackTrace();
}
}catch (NoSuchMethodException | IllegalArgumentException | IllegalAccessException e) {
Log.e(TAG, "Fallo al hacer visibile el dispositivo.", e);}
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/