Is there any way to get a the list of connected MAC addresses when my phone is on Wi-Fi tethering mode?
Firstly, you must have a rooted device. When it's done just read dnsmasq.leases file. Usually it is placed at: /data/misc/dhcp/dnsmasq.leases.
A structure of the file is pretty simple - each line is a summary of a connected user. The summary has several fields including MAC.
I didn't find a possibility to get MAC without root. Please correct me if I'm wrong.
Reading /proc/net/arp would provide the information for both static and DHCP clients that have communicated with the device during the last 60 seconds (configured in /proc/sys/net/ipv4/neigh/wl0.1/gc_stale_time where wl0.1 is the wireless network interface on my phone).
It is available for non-root users too.
#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;
}
public static ArrayList<String> getConnectedDevicesMac()
{
ArrayList<String> res = new ArrayList<String>();
//NetManager.updateArpFile();
BufferedReader br;
try
{
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
line = br.readLine();
while ((line = br.readLine()) != null)
{
String[] sp = line.split(" +");
if (sp[3].matches("..:..:..:..:..:.."))
res.add(sp[3]);
}
br.close();
}
catch (Exception e)
{}
return res;
}
Related
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 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 am using the following code to call android equipment ping command:
public static String pingServer() {
PingResult result = new PingResult();
String jsonString = null;
try {
String command = "ping -c 3 192.168.8.185";
Process p = Runtime.getRuntime().exec(command);
int status = p.waitFor();
InputStream input = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = in.readLine()) != null) {
buffer.append(line);
buffer.append("\n");
}
String bufferStr = buffer.toString();
System.out.println(bufferStr);
} catch (Exception e) {
System.out.println("---------------exception-----------ping");
System.out.println(e.getMessage());
// e.printStackTrace();
}
}
BufferStr always obtain the last line data.
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
The details result can be get.
It may be simpler and easier to use InetAddress.isReachable:
if (InetAddress.getByName("192.168.8.185").isReachable(6000))
...
I want to save my app logcat events in a text file on sd card.
my alarming app work properly in my and my friends devices, but other have error on my app.
for example they say alarms in app are in wrong time, but i dont see this error in my and my friends devices.
Because of this issue and other issues, i want save all events logcat related my app, atomatically. so they send log file to me to solve issues.
how can i do this?
thanks
sorry for my bad english
You can get logcat via the following:
static final int BUFFER_SIZE = 1024;
public String getLogCat() {
String[] logcatArgs = new String[] {"logcat", "-v", "time"};
Process logcatProc = null;
try {
logcatProc = Runtime.getRuntime().exec(logcatArgs);
}
catch (IOException e) {
return null;
}
BufferedReader reader = null;
String response = null;
try {
String separator = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(logcatProc.getInputStream()), BUFFER_SIZE);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append(separator);
}
response = sb.toString();
}
catch (IOException e) {
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {}
}
}
return response;
}
You can then save this String to the sdcard.
You can get logcat via the following:
static final int BUFFER_SIZE = 1024;
public String getLogCat() {
String[] logcatArgs = new String[] {"logcat", "-v", "time"};
Process logcatProc = null;
try {
logcatProc = Runtime.getRuntime().exec(logcatArgs);
}
catch (IOException e) {
return null;
}
BufferedReader reader = null;
String response = null;
try {
String separator = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(logcatProc.getInputStream()), BUFFER_SIZE);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append(separator);
}
response = sb.toString();
}
catch (IOException e) {
}
finally {
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {}
}
}
return response;
}
You can then save this String to the sdcard.
This answer from "Dororo" didn't work for me since it always got stuck in the while due to to many lines, but i have no idea how to fix that.
the logcat will block for reading new logs unless you specify the '-d' arg.
try
String[] logcatArgs = new String[] {"logcat", "-d", "-v", "time"};
This type of functionality is already implemented by the ACRA Android library. The library detects crashes, and send the crash information to either a Google Docs spreadsheet, or your own destination.
Execute within a thread to avoid ANRs
I have an android tab with hotspot turned on. When other wifi enabled devices get connected to my android device , their IP Address and other details get stored in the ARP table and I can access those details by reading from "/proc/net/arp" and I am showing them in a list. But when one device gets disconneted from my hotspot enabled android tab then the corresponding details related to that device are not getting cleared from the ARP table(When I read "/proc/net/arp" , the ARP table still holds the details of disconnected device). I want to Clear the details of the device which is disconnected.
Here is the code (accessing ARP table)
public ArrayList<ClientScanResultSO> getClientList(boolean onlyReachables,
int reachableTimeout) {
BufferedReader br = null;
ArrayList<ClientScanResultSO> result = null;
try {
result = new ArrayList<ClientScanResultSO>();
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 mac = splitted[3];
if (mac.matches("..:..:..:..:..:..")) {
boolean isReachable = InetAddress
.getByName(splitted[0]).isReachable(
reachableTimeout);
String name = InetAddress.getByName(splitted[0]).getHostName();
if (!onlyReachables || isReachable) {
result.add(new ClientScanResultSO(splitted[0],
splitted[3], splitted[5], isReachable,name));
}
}
}
}
} 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;
}
Hope I am clear with my question.