前言:
遇到一个Android+web服务的项目, 做app端时遇到要扫描wifi内的其他ip地址, 之后在网上找了好久, 试过WifiManager不过只能获取bssid,据说就是mac地址,但不是ip啊,然后想使用android底层的Linus的shell命令,搞了不天也不懂...好在最后参考网上帖子. 总算是有眉目了,但是后边说项目不用了,我去...但是不能浪费,[color=red]虽然不是完全版,还有问题,但是可以运行[/color],或许以后用的着.另外,不喜勿喷!

思路:
app连接wifi后,会存在一个ip地址, 和电脑一样,那么局域网内的其他机器也在这个网段, 所以 [color=red]通过本地ip获得相应网段,然后通过ping遍历网段ip,获取同网段局域网ip,以达到目的![/color]
代码:
1,给app分配权限

<!--允许应用程序改变网络状态--> 

 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> 

 <!--允许应用程序改变WIFI连接状态--> 

 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> 

 <!--允许应用程序访问WIFI网卡的网络信息--> 

 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 

 <!--允许应用程序完全使用网络--> 

 <uses-permission android:name="android.permission.INTERNET"/> 

 <!--允许访问网络状态--> 

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />



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 List<String> ipListInSameSegment = 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<ScanResult> mWifiList;
    //网络连接列表
    private List<WifiConfiguration> 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<String> 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();
List<String> ipList = netUtil.scanIpInSameSegment();
String ips ="扫描到的ip:\n";
for(String str:ipList){
       ips+=str+"\n";
 }
Toast.makeText(LoginActivity.this,ips,Toast.LENGTH_SHORT).show();


4.效果

android 搜索局域网 android 局域网扫描_android

android 搜索局域网 android 局域网扫描_android 搜索局域网_02



5.说明


NetUtil包括调用android内的WifiManger,通过它获得本地wifi信息包括ip(例如192.168.0.1), 获得网段,也就是192.168.0.X,X代表要遍历的ip最后一段,其中使用当前运行时状态,用来ping其他ip测试是否连通,注意: [color=darkred]使用Runtime.exec(command)ping时,必须获得root权限[/color],否则不同.这也是网上很多的ping例子但是,不通的原因,或许像我这种小白菜不知道要root.这让我浪费好多时间啊 .然后NetUtil后边有获取root和判断是否root的方法.



6.权限问题


里面使用256个进程去ping, 这里没有做处理,导致主线程运行完了,这256个线程还没跑完, 返回的结果可能不对,需要使用debug,让256个线程跑完后再继续运行主线程才能到达预期效果. 提供个连接或许能有帮助