I'm currently working on a larger project, with a python backend running on Windows and an Android App for the frontend. Since this is just a prototype for a university project, both the backend and the app are expected to be running in a local network only.
There is a need to send bidirectional messages between those parts to notify each other about changes in the database. To achieve this, I'm using the socketserver package for a server in the python backend. As described here, a handler factory is used to get a callback function to handle the incoming data. This works fine for all messaging needs from App (client) to Backend (server).
When connecting to this server from the app, the first message is used to retrieve the IP of the connected client (on the app). Using this IP and the callback the backend tries to connect to the App, now acting as a client. (Backend = Client, App = Server → inverse connection). At this point my problem starts, when the App is running on a real phone, everything works just fine, but when its running in Android Studios emulator I'm getting a ConnectionRefusedError
.
MWE
To isolate this issue, I created a MWE with just the Android Server and Python Client, reproducing the same issues as in the large project. Even though it shouldn't interfere with this, I also tried to fully disable the windows firewall for these tests, but it didn't make a difference (as expected).
Android Server
Create new project with an empty activity, add the internet permission to the android manifest and the androidx.lifecycle:lifecycle-runtime-ktx:2.2.0
dependency for coroutines. This server is running either in an Android Studios emulator or on a real phone. On the real device, it works just fine, but in the emulator it fails, which is the problem to be saved with this question.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch(Dispatchers.IO){
val server = ServerSocket(48023)
while (true){
val socket = server.accept()
val input = socket.getInputStream()
var messageBuffer = ByteArray(1024)
val numRead = input.read(messageBuffer)
val message = messageBuffer.decodeToString()
Log.d("CustomLog", message)
socket.close()
}
}
}
}
Python client
According to this answer, the correct IP to use should be 10.0.2.15
. However, to make sure I didn't missunderstand something I tried all of them, getting either timeouts or connectionRefused erros. This client is running on a Windows PC.
import socket
HOST_IP = "10.0.2.15"
PORT = 48023
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((HOST_IP,PORT))
s.sendall(b"Hello World!")
print("done")
s.close()
The solution I'm looking for
There are two options:
- Figure out why the backend client can't connect to the android server in the emulator.
- Point me to an alternative way of sending bidirectional messages between app and backend. I couldn't figure out how to send a message from the backend server to the app client, without the client asking for it. Therefore I'm trying to use the beforementioned server and client in both backend and frontend.
P.S. Feel free to correct any language misstages, I'm a non native speaker.