Android does not detect a captive portal
I have this exact same setup and was having the same problem. I solved this by having the web server return some content as well as the status code. In my case, I had the web server respond with the index page for any requests not found on the web server.

Note that this is being done by an access point that does have internet access.