简体   繁体   中英

Trying to send data over WiFi to an ESP32 from an Android app - Data seemingly not sending

I'm more OK with the C++ on the ESP32 (arduino IDE) than I am with the Java of the Android app so I think the problem is laying with the Java code not actually sending any data.

Here is expected behaviour:

  1. ESP32 initiates as an access point (they have all have WiFi chips so can be programmed as so)
  2. Android devices goes to.network settings and connects to the ESP32 hotspot/access point
  3. Android device goes back to the app and presses a button to send a string of data
  4. ESP32 is listening for any data ending with '\n' to then blink an onboard LED. In the case of my Java code the code for sending is using the PrintWriter class and the println method (meaning any data sent will have '\n' as a suffix

I made the APK today and installed it on an android phone, fired up the ESP32 and checked the serial monitor to make sure the IP is the same as what I have specified in the Java code, the port (80) is also the same.

I connect to the ESP32 from my Android device and go back to the app, press the button and nothing happens. The serial monitor in the Arduino IDE for the ESP32 is also showing nothing (it should print the received data).

So I'll paste the Java code, which is where I think the error might be. As you can see I am trying to send "Hello ESP32" as a string.

package com.benledmatrix.esp32controloverwifi;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set up a button to send data when clicked
        Button sendButton = findViewById(R.id.send_button);
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendData();
            }
        });
    }

    private void sendData() {
        // Set up a thread to send the data in the background
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // Connect to the ESP32's IP address and port
                    Socket socket = new Socket("192.168.4.1", 80);
                    PrintWriter out = new PrintWriter(socket.getOutputStream());

                    // Send the data
                    out.println("Hello, ESP32!");
                    out.flush();

                    // Close the connection
                    out.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

And here is the Arduino C++ code that is on the ESP32

#include <WiFi.h>

const char* ssid = "ESP32 HotSpot";
const char* password = "password";

WiFiServer server(80);  // Create a server on port 80

void setup() {

  Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  Serial.print("IP address: ");
  Serial.println(WiFi.softAPIP());
  server.begin();      // Start the server
  pinMode(2, OUTPUT);  // Set onboard LED as an output
}

void loop() {
  WiFiClient client = server.available();  // Listen for incoming clients

  if (client) {                                  // If a client connects
    String data = client.readStringUntil('\n');  // Read the data from the client
    Serial.println(data);                        // Print the data to the serial monitor

    if (data == "Hello, ESP32!") {  // If the data is "Hello, ESP32!"
      // Flash the onboard LED twice
      for (int i = 0; i < 2; i++) {
        digitalWrite(2, HIGH);
        delay(200);
        digitalWrite(2, LOW);
        delay(200);
      }
    } else {
      // Flash the onboard LED once
      digitalWrite(2, HIGH);
      delay(200);
      digitalWrite(2, LOW);
      delay(200);
    }

    client.stop();  // Disconnect the client
  }
}

And just in case I am being a complete div here is the XML code for the button:D you never know

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/send_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:background="#008080"
            android:text="Send Data" />

    </RelativeLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

Sorry for such a dump but as I'm not that experienced with Android I thought it best to put everything in there. It compiles fine and no bugs found but just doesn't do the desired action.

If someone has an idea I will try it. Many thanks Ben

After much research I have a functioning code that, when pressing the "Send Data" button on the Android app, it blinks the onboard LED of the ESP32 twice to signify it has received the string. Very happy!

In the end the reason was I did not have any permission to use the inte.net. I used the USB debugging and put in some log.d and it showed me I didn't have access to use the inte.net so putting in that permission and some toast messages to check the permission fixed it.

C++ and XML code remained the same but in the Android XML manifest file I added:

<uses-permission android:name="android.permission.INTERNET" />

And the final Java code is as follows:

package com.benledmatrix.esp32controloverwifi;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;


public class MainActivity extends AppCompatActivity {

    private static final int PERMISSION_REQUEST_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Check for Internet permission for SDK 23 or higher
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.INTERNET)) {

                //rationale to display why the permission is needed
                Toast.makeText(this, "The app needs access to the Internet to send data to the ESP32", Toast.LENGTH_SHORT).show();
            }
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET}, PERMISSION_REQUEST_CODE);
        }

        // Set up a button to send data when clicked
        Button sendButton = findViewById(R.id.send_button);
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendData();
            }
        });
    }

    //Check for result of permissions and feedback accordingly
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission granted, you can perform the network operation here
                Log.d("Permission", "Granted");
            } else {
                // Permission denied, show a message to the user
                Log.d("Permission", "Denied");
                Toast.makeText(this, "Permission denied, you cannot perform network operations", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void sendData() {
        // Set up a thread to send the data in the background
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // Connect to the ESP32's IP address and port
                    Log.d("Sending Data", "Button Pressed, connecting to ESP32.....");
                    Socket socket = new Socket("192.168.4.1", 80);
                    PrintWriter out = new PrintWriter(socket.getOutputStream());

                    // Send the data
                    out.println("Hello, ESP32!");
                    out.flush();
                    Log.d("Sending Data", "Data Sent!");

                    // Close the connection
                    out.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("Sending Data", "Error Sending Data: "+e.getMessage());
                }
            }
        }).start();
    }
}

Of course any further advice on things I perhaps don't need or improvements I could make would be great.

Many thanks Ben

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM