Cross post with https://stackoverflow.com/questions/52596484/connect-android-and-pi-3-via-network-socket-using-pi-3-as-an-access-point, please delete if this isn't allowed.
My plan here is to create an access point on the Pi 3 using the interface wlan0
which has been setup using hostapd
. I run the command hostapd /etc/hostapd/hostapd.conf
to start up the network and then I want to connect to it with the Android and setup a socket.
Currently, the network enables on the Pi 3 without issue, but creating the socket on Android is throwing
java.net.ConnectException: failed to connect to /192.168.42.1 (port 80) after 500ms: connect failed: ENETUNREACH (Network is unreachable)
.
I am using the IP of Pi's wlan0
to create my socket as you can see (on Android code). I will post the output of the Pi's Python script as well as some information about the network.
I have the following Python 3 code on my Pi 3 (server):
import socket
import os
os.system('hostapd /etc/hostapd/hostapd.conf &')
print('started access point service')
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('192.168.42.1', 80))
serversocket.listen(1)
connection, address = serversocket.accept()
b = connection.recv(1024)
print(b)
serversocket.close()
connection.shutdown(socket.SHUT_WR)
connection.close()
Android code regarding the wifi socket connection (client). Joins the network using its' SSID:
// enable Wifi
wifiManager.setWifiEnabled(true);
// connect to the network access point created by the Pi 3
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + blackBoxSSID + "\"";
wifiConfiguration.preSharedKey = "\"" + blackBoxNetworkPassword + "\"";
wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
int netID = wifiManager.addNetwork(wifiConfiguration);
if (netID == -1) {
netID = getExistingNetworkID(wifiConfiguration.SSID);
}
wifiManager.disconnect();
wifiManager.enableNetwork(netID, true);
wifiManager.reconnect();
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Log.d(TAG, "current netID " + netID + ", current SSID " + wifiInfo.getSSID());
Log.d(TAG, "current IP of wifi device: " + wifiInfo.getIpAddress() + ", HW address: " + wifiInfo.getMacAddress());
// start the server socket process
startServerSocket();
Helper functions:
private void startServerSocket() {
Log.i(TAG, "Starting server socket thread");
Thread serverSocketThread = new Thread(new Runnable() {
@Override
public void run() {
try {
Socket socket = new Socket();
socket.bind(null);
socket.connect(new InetSocketAddress("192.168.42.1", 80), 500);
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeBytes("Hello black box");
dataOutputStream.writeBytes("Hello black box");
dataOutputStream.writeBytes("Hello black box");
dataOutputStream.writeBytes("Hello black box");
dataOutputStream.writeBytes("Hello black box");
dataOutputStream.writeBytes("Hello black box");
socket.close();
} catch (IOException e) {
Log.e(TAG, "Error creating ServerSocket and Socket object:", e);
}
}
});
serverSocketThread.start();
Log.d(TAG, "started server socket thread");
}
and
private int getExistingNetworkID(String SSID) {
WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> configuredNetworks = wifiManager.getConfiguredNetworks();
if (configuredNetworks != null) {
for (WifiConfiguration existingConfig : configuredNetworks) {
if (existingConfig.SSID.equals(SSID)) {
return existingConfig.networkId;
}
}
}
return -1;
}
here's the manifest file:
<!-- Wifi/Internet-related permissions -->
<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_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
The Android code returns
current netID 617, current SSID "NetworkName" current IP of wifi device: 0, HW address: <hw address of something but not wlan0>
, which means the correct network is connected without issue.
The Python code returns
started access point service
Configuration file: /etc/hostapd/hostapd.conf
Failed to create interface mon.wlan0: -95 (Operation not supported)
wlan0: interface state UNINITIALIZED->COUNTRY_UPDATE
wlan0: Could not connect to kernel driver
Using interface wlan0 with hwaddr <wlan0 hw address> and ssid "NetworkName"
listening on port 80
wlan0: interface state COUNTRY_UPDATE->ENABLED
wlan0: AP-ENABLED
and all wifi devices I have can see the network and connect using the password.
For more info here is the hostapd.conf
file:
interface=wlan0
#driver=nl80211
ssid=Coriolis
country_code=CA
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=password123
wpa_key_mgmt=WPA-PSK
wpa_group_rekey=86400
ieee80211n=1
wpa_pairwise=TKIP
rsn_pairwise=CCMP
wme_enabled=1
sorry about the indentation inside some of the code snippets, using the {} code button puts this in and I can't seem to get rid of it without removing the code formatting.
Edit:
Here is the contents of /etc/dnsmasq.conf
:
interface=wlan0
dhcp-range=192.168.42.2,192.168.42.4,255.255.255.0,24h
dnsmasq
and hostapd
services are both active (running)
If I manually go and select Wifi then connect using the WPA password, the device associates then disassociates with the Pi 3, then reads AP-STA-CONNECTED
with pairwise key handshake completed (RSN)
. So clearly my Android code is doing something weird. But doing this crashes the app with a RuntimeException; unable to instantiate receiver (wifiReceiver - which doesn't exist)
and ClassNotFoundException: didn't find class (wifiReceiver) on path: DexPathList
. It seems like this is a completely internal call as well, there are no tracebacks to my actual code.