遇到一个Android+web服务的项目, 做app端时遇到要扫描wifi内的其他ip地址, 之后在网上找了好久, 试过WifiManager不过只能获取bssid,据说就是mac地址,但不是ip啊,然后想使用android底层的Linus的shell命令,搞了不天也不懂...好在最后参考网上帖子. 总算是有眉目了,但是后边说项目不用了,我去...但是不能浪费, 虽然不是完全版,还有问题,但是可以运行,或许以后用的着.另外,不喜勿喷!
思路:
app连接wifi后,会存在一个ip地址, 和电脑一样,那么局域网内的其他机器也在这个网段, 所以 通过本地ip获得相应网段,然后通过ping遍历网段ip,获取同网段局域网ip,以达到目的!
代码:
1,给app分配权限
2,NetUtil.java
import android.content.Context; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.util.Log; import android.widget.Toast; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; /** * 获得当前网络信息,已经扫描同网段的ip * Created by Albert.Ma on 2015/8/25. */ public class NetUtil { private Context context; private String localIpAddress;//本地ip地址 如 192.168.0.1 private String networkSegment;//本地网段 如 192.168.0. private int ipIndex;//ip最后位 如 1 private volatile ListipListInSameSegment = new ArrayList<>();//存放同网段的ip private boolean isRoot=false;//是否root private String ping = "ping -c 3 -w 10 ";//-c 是指ping的次数 -w 100 以秒为单位指定超时间 private Runtime runtime = Runtime.getRuntime(); private Process process = null; //定义WifiManager对象 private WifiManager mWifiManager; //定义WifiInfo对象 private WifiInfo mWifiInfo; //扫描出的网络连接列表 private List mWifiList; //网络连接列表 private List mWifiConfiguration; //定义一个WifiLock WifiManager.WifiLock mWifiLock; //判断是否root private final static int kSystemRootStateUnknow = -1; private final static int kSystemRootStateDisable = 0; private final static int kSystemRootStateEnable = 1; private static int systemRootState = kSystemRootStateUnknow; public NetUtil(Context context){ this.context = context; //取得WifiManager对象 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); //取得WifiInfo对象 mWifiInfo = mWifiManager.getConnectionInfo(); mWifiManager.startScan(); //得到扫描结果 mWifiList = mWifiManager.getScanResults(); //得到配置好的网络连接 mWifiConfiguration = mWifiManager.getConfiguredNetworks(); //设置本地ip String ip = getLocalIpAddress().toString(); localIpAddress = ip.substring(1, ip.length()); networkSegment = this.localIpAddress.substring(0, this.localIpAddress.lastIndexOf(".") + 1); } /** * 获取本地ip */ public InetAddress getLocalIpAddress() { int hostAddress = mWifiInfo.getIpAddress(); byte[] addressBytes = { (byte)(0xff & hostAddress), (byte)(0xff & (hostAddress >> 8)), (byte)(0xff & (hostAddress >> 16)), (byte)(0xff & (hostAddress >> 24)) }; try { return InetAddress.getByAddress(addressBytes); } catch (UnknownHostException e) { throw new AssertionError(); } } /** * 扫描同网段的ip */ public List scanIpInSameSegment(){ if(this.localIpAddress == null || "".equals(this.localIpAddress)){ // Toast.makeText(context, "扫描失败,请检查wifi网络", Toast.LENGTH_LONG).show(); return null; } if(!NetUtil.isRootSystem()){ Toast.makeText(context, "扫描网络ip需要root权限,请先root后再尝试!", Toast.LENGTH_LONG).show(); return null; } //产生256个线程测试ip for(int i=0;i<256;i++){ ipIndex = i; new Thread(new Runnable() { @Override public synchronized void run() { String currentIp = networkSegment + ipIndex; String command = ping + currentIp; try { process = runtime.exec(command); int result = process.waitFor(); if (result == 0) { System.out.println("连接成功:" + currentIp); Log.i("IP", "连接成功:" + currentIp); ipListInSameSegment.add(currentIp); } else { System.out.println("连接失败:" + currentIp); Log.i("IP", "连接失败:" + currentIp); } } catch (IOException e1) { e1.printStackTrace(); } catch (InterruptedException e2) { e2.printStackTrace(); } finally { process.destroy(); } } }).start(); } return ipListInSameSegment; } /** * 获得root权限 */ public void getRootPermission(){ if(NetUtil.isRootSystem()){ return; } try { String rootCommand = "su"; process = runtime.exec(rootCommand); int result = process.waitFor(); if (result == 0) { this.isRoot = true; Log.i("IP", "Root成功"); Toast.makeText(context, "Root成功", Toast.LENGTH_SHORT).show(); } else { Log.i("IP", "Root失败"); Toast.makeText(context, "Root失败", Toast.LENGTH_SHORT).show(); } // //输出结果 // BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); // String line = null; // while ((line = in.readLine()) != null) { // Log.i("IP", ">>>:" + line); // } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 判断是否已经root */ public static boolean isRootSystem() { if (systemRootState == kSystemRootStateEnable) { return true; } else if (systemRootState == kSystemRootStateDisable) { return false; } File f = null; final String kSuSearchPaths[] = { "/system/bin/", "/system/xbin/", "/system/sbin/", "/sbin/", "/vendor/bin/" }; try { for (int i = 0; i < kSuSearchPaths.length; i++) { f = new File(kSuSearchPaths[i] + "su"); if (f != null && f.exists()) { systemRootState = kSystemRootStateEnable; return true; } } } catch (Exception e) { } systemRootState = kSystemRootStateDisable; return false; } }
3,调用
NetUtil netUtil =new NetUtil(this); netUtil.getRootPermission(); ListipList = netUtil.scanIpInSameSegment(); String ips ="扫描到的ip:\n"; for(String str:ipList){ ips+=str+"\n"; } Toast.makeText(LoginActivity.this,ips,Toast.LENGTH_SHORT).show();
4.效果
5.说明
NetUtil包括调用android内的WifiManger,通过它获得本地wifi信息包括ip(例如192.168.0.1), 获得网段,也就是192.168.0.X,X代表要遍历的ip最后一段,其中使用当前运行时状态,用来ping其他ip测试是否连通,注意: 使用Runtime.exec(command)ping时,必须获得root权限,否则不同.这也是网上很多的ping例子但是,不通的原因,或许像我这种小白菜不知道要root.这让我浪费好多时间啊 .然后NetUtil后边有获取root和判断是否root的方法.
6.权限问题
里面使用256个进程去ping, 这里没有做处理,导致主线程运行完了,这256个线程还没跑完, 返回的结果可能不对,需要使用debug,让256个线程跑完后再继续运行主线程才能到达预期效果. 提供个连接或许能有帮助 http://blog.csdn.net/escaflone/article/details/10418651