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..
Related
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
It's giving a null pointer exception.I would like to get the IP address of a device connected via wifi direct.How to do this can anyone explain?Attached a Screen to see.
Thanks in advance.
You can use following code snippet, When WiFiP2pInfo has connection then it is not null but when there is no connection or connection lost then it will be null.
if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION
.equals(action)) {
if (manager == null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
if (networkInfo.isConnected()) {
manager.requestConnectionInfo(channel,
new ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(
WifiP2pInfo info) {
if (info != null) {
activity.setConnectionInfo(info); // When connection is established with other device, We can find that info from wifiP2pInfo here.
}
}
}
);
} else {
activity.resetData(); // When connection lost then we can reset data w.r.t that connection.
}
}
Following code helps to find address of Client and Owner,
public static String getDestinationDeviceIpAddress(WifiP2pInfo wifiP2pInfo) {
String destinationAddress;
if (wifiP2pInfo.isGroupOwner) {
destinationAddress = WifiDirectUtil.getIPFromMac();
} else {
destinationAddress = wifiP2pInfo.groupOwnerAddress.getHostAddress();
}
return destinationAddress;
}
public static String getIPFromMac() {
BufferedReader br = null;
boolean isFirstLine = true;
String ipAddress = null;
try {
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
if (isFirstLine) {
isFirstLine = false;
continue;
}
String[] splitted = line.split(" +");
Log.d(TAG, "** length **" + splitted.length);
if (splitted.length >= 4) {
String device = splitted[5];
Log.d(TAG, device);
if (device.contains("p2p")) {
ipAddress = splitted[0];
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return ipAddress;
}
And add permission Read External storage in manifest.xml.
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 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.