I was trying to make an app that can find the IP address of a device connected to my android phone's hotspot using it's MAC address. I know this can be done using ARP tables but I just don't know how. I'm using android studio with java and my device is running android 10. Please help.
Here's how it's implemented in AndroidNetworkTools library, which worked fine for me:
/**
* Returns all the IP/MAC address pairs currently in the ARP cache (/proc/net/arp).
*/
public static HashMap<String, String> getAllIPAndMACAddressesInARPCache() {
HashMap<String, String> macList = new HashMap<>();
for (String line : getLinesInARPCache()) {
String[] splitted = line.split(" +");
if (splitted.length >= 4) {
// Ignore values with invalid MAC addresses
if (splitted[3].matches("..:..:..:..:..:..")
&& !splitted[3].equals("00:00:00:00:00:00")) {
macList.put(splitted[0], splitted[3]);
}
}
}
return macList;
}
/**
* Method to read lines from the ARP Cache
*/
private static ArrayList<String> getLinesInARPCache() {
ArrayList<String> lines = new ArrayList<>();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
lines.add(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return lines;
}
In Android,
How to get the list of devices connected in same WiFi Network?
How to get the nearest devices from your smartphone connected with same WiFi network?
Did frequency check is able to find the nearest device?
I find the solution for list of devices connected in same network,and i placed the code below
Call this method in onCreate -> getClientList(true, 200);
write this method in our class
public ArrayList<ClientScanResult> getClientList(boolean onlyReachables, int reachableTimeout) {
BufferedReader br = null;
ArrayList<ClientScanResult> result = null;
try {
result = new ArrayList<ClientScanResult>();
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
int i = 0;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if ((splitted != null) && (splitted.length >= 4)) {
String mac = splitted[3];
if (mac.matches("..:..:..:..:..:..")) {
boolean isReachable = InetAddress.getByName(splitted[0]).isReachable(reachableTimeout);
if (!onlyReachables || isReachable) {
result.add(new ClientScanResult(splitted[0], splitted[3], splitted[5], isReachable));
i++;
}
}
}
}
} catch (Exception e) {
Log.e(this.getClass().toString(), e.getMessage());
} finally {
try {
br.close();
} catch (IOException e) {
Log.e(this.getClass().toString(), e.getMessage());
}
}
return result;
}
if any clarifications, please reply a message for this post,
THANKS
I was able to connect the WiFi Direct device from Application, While connecting Device is acting as Group Owner and Non-Group Owner. I mainly face this issue in Nexus device. After connecting if device act as Group Owner, then wrong IP Address is showing. This is the code I am using.
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = mPeers.get(arg2).deviceAddress;
config.wps.setup = WpsInfo.PBC;
config.groupOwnerIntent=0;
mWifiP2pManager.connect(mChannel, config, new ActionListener() {
#Override
public void onSuccess() {
isconnected=true;
}
#Override
public void onFailure(int reason) {
Toast.makeText(ConfigureNetworkActivity.this, "Connect failed."+reason,
Toast.LENGTH_SHORT).show();
}
});
I am using this code to retrieve the IP Address.
info.groupOwnerAddress.getHostAddress();
How we can we retrieve correct IP address, if Device act as Group Owner after connection?
Thanks In Advance.
By using this code I am able to retrieve the IP Address of Connected WiFi Direct device. If it is Group Owner.
public static String getIPFromMac(String MAC) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if (splitted != null && splitted.length >= 4) {
// Basic sanity check
String device = splitted[5];
if (device.matches(".*p2p-p2p0.*")){
String mac = splitted[3];
if (mac.matches(MAC)) {
return splitted[0];
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
Thanks..
I am connecting different devices with wifi hotspot AP programatically in my android app, How can i detect the clients being connected and disconnected and to the wifi hotspot AP Programmatically ? Is there any callback event in Android API to give information regarding the connection or disconnection events of individual devices ? Thanks in advance.
Unfortunately there is no public API to give information about this...
But you can read /proc/net/arp file and see the clients connected to your Access Point.
/proc/net/arp file have 6 fields: IP address, HW type, Flags, HW address, Mask and Device
The problem is when a client get disconnected, because it doesn't disappear from the file. A solution may be to do ping to every client and wait for response, but for me this isn't a good solution because some clients don't respond to ping. If you like this solution check this project on GitHub --> https://github.com/nickrussler/Android-Wifi-Hotspot-Manager-Class/tree/master/src/com/whitebyte
What i have did is: read /proc/net/arp and check the FLAGS field, when the value is 0x2 the station is connected and 0x0 is disconnected, but to refresh this field I need to clear ARP cache from time to time, and i did it with this command: ip neigh flush all
I hope i helped you
This method works for me but this is detecting only version 4.0 and above; it is not able to find the devices with version 2.2 or 2.3 which is connected with hotspot.
public void getClientList() {
int macCount = 0;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if (splitted != null ) {
// Basic sanity check
String mac = splitted[3];
System.out.println("Mac : Outside If "+ mac );
if (mac.matches("..:..:..:..:..:..")) {
macCount++;
/* ClientList.add("Client(" + macCount + ")");
IpAddr.add(splitted[0]);
HWAddr.add(splitted[3]);
Device.add(splitted[5]);*/
System.out.println("Mac : "+ mac + " IP Address : "+splitted[0] );
System.out.println("Mac_Count " + macCount + " MAC_ADDRESS "+ mac);
Toast.makeText(
getApplicationContext(),
"Mac_Count " + macCount + " MAC_ADDRESS "
+ mac, Toast.LENGTH_SHORT).show();
}
/* for (int i = 0; i < splitted.length; i++)
System.out.println("Addressssssss "+ splitted[i]);*/
}
}
} catch(Exception e) {
}
}
Android 10 restricts the permission for access to the /proc/net directory, so some of the solutions above are no longer feasible, but the 'ip' command is still available
private fun getARPIps(): List<Pair<String, String>> {
val result = mutableListOf<Pair<String, String>>()
try {
// val args = listOf("ip", "neigh")
// val cmd = ProcessBuilder(args)
// val process: Process = cmd.start()
val process = Runtime.getRuntime().exec("ip neigh")
val reader = BufferedReader(InputStreamReader(process.inputStream))
reader.forEachLine {
if (!it.contains("FAILED")) {
val split = it.split("\\s+".toRegex())
if (split.size > 4 && split[0].matches(Regex("([0-9]{1,3}\\.){3}[0-9]{1,3}"))) {
result.add(Pair(split[0], split[4]))
}
}
}
val errReader = BufferedReader(InputStreamReader(process.errorStream))
errReader.forEachLine {
Log.e(TAG, it)
// post the error message to server
}
reader.close()
errReader.close()
process.destroy()
} catch (e: Exception){
e.printStackTrace()
// post the error message to server
}
return result
}
#SuppressWarnings("ConstantConditions")
public static String getClientMacByIP(String ip)
{
String res = "";
if (ip == null)
return res;
String flushCmd = "sh ip -s -s neigh flush all";
Runtime runtime = Runtime.getRuntime();
try
{
runtime.exec(flushCmd,null,new File("/proc/net"));
}
BufferedReader br;
try
{
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null)
{
String[] sp = line.split(" +");
if (sp.length >= 4 && ip.equals(sp[0]))
{Assistance.Log(sp[0]+sp[2]+sp[3],ALERT_STATES.ALERT_STATE_LOG);
String mac = sp[3];
if (mac.matches("..:..:..:..:..:..") && sp[2].equals("0x2"))
{
res = mac;
break;
}
}
}
br.close();
}
catch (Exception e)
{}
return res;
}
//--------------------------------------------------------
#SuppressWarnings("ConstantConditions")
public static String getClientIPByMac(String mac)
{
String res = "";
if (mac == null)
return res;
String flushCmd = "sh ip -s -s neigh flush all";
Runtime runtime = Runtime.getRuntime();
try
{
runtime.exec(flushCmd,null,new File("/proc/net"));
}
BufferedReader br;
try
{
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null)
{
String[] sp = line.split(" +");
if (sp.length >= 4 && mac.equals(sp[3]))
{
String ip = sp[0];
if (ip.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}") && sp[2].equals("0x2"))
{
res = ip;
break;
}
}
}
br.close();
}
catch (Exception e)
{}
return res;
}
you can use BroadcastReciever "android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED" to detect client connection.
In your AndroidManifest:
<receiver
android:name=".WiFiConnectionReciever"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED" />
</intent-filter>
</receiver>
and in your activity
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction("android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED");
rcv = new WiFiConnectionReciever();
registerReceiver(rcv,
mIntentFilter);
I have a question:
Is there any why to get a notification (intent, broadcast etc..) in my MainActivity when a client connects to the Wifi Access Point I openend before?
I want to print information about connected clients to a console when they connect.
thanks for any help!
try {
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if (splitted != null && splitted.length >= 4) {
String mac = splitted[3];
if (mac.matches("..:..:..:..:..:..")) {
macCount++;
}
}
}
} catch (Exception e) { e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}