android 周边设备信息采集

       现在大数据做的越来越变态,要求可以根据周边设备来完成。不讨论其他,就技术实现,其实很简单。

       周边设备定义:同一路由下的周边设备,不局限android设备

       实现原理:同一网段下,是根据Mac来通讯的。android设备上面,存储这ip和Mac一一对应的关系,是在arp表里面。

                        该信息存放在/proc/net/arp里面 。

     

      实现步骤:1、解析/proc/net/arp文件,得到ip和Mac信息

                        2、考虑设备有可能没有和其他设备有通讯过,arp表没有缓存信息。

                        3、主动和同网段下,0-255的ip地址进行通讯,可以执行ping 命令或者发送udp包

                        4、重新读取/proc/net/arp

 

下面是一个demo,仅供参考。

            demo兼容有线、wifi联网模式。

            demo使用的是udp来更新arp信息。

            demo内部处理网络是否连接的情况。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

import static CollectMacInterface.Collect_Mac_IO_ERROR;
import static CollectMacInterface.Collect_Mac_Interrupt_ERROR;
import static CollectMacInterface.IP_Format_ERROR;
import static CollectMacInterface.Multiple_Call_ERROR;
import static CollectMacInterface.Not_Connect_ERROR;
import static CollectMacInterface.Not_IP_ERROR;
import static CollectMacInterface.Not_Need_ERROR;
import static CollectMacInterface.Not_Route_ERROR;

public class CollectMacThread
{
    private ExecutorService threadPool = null;
    private Context mContext = null;
    private boolean isCollectMac = false;
    private final static String TAG = "CollectMacThread";
    private NetBroadcastReceiver receiver = null;
    private HashMap<String, String> ipAndMac = new HashMap<String, String>();
    private String routeMac = "";
    private volatile boolean hasInit = false;

    public CollectMacThread()
    {
        threadPool = Executors.newSingleThreadExecutor();
    }

    public void start(Context context, boolean forceResearch, CollectMacInterface listener)
    {
        mContext = context;
        if (threadPool != null)
        {
            threadPool.shutdownNow();
            threadPool = null;
        }
        threadPool = Executors.newSingleThreadExecutor();
        this.isForceResearch = forceResearch;
        this.collectMacInterface = listener;
        threadPool.submit(new CollectRunnable(forceResearch, listener));
    }

    private boolean isForceResearch = false;
    private CollectMacInterface collectMacInterface = null;

    private class CollectRunnable implements Runnable
    {
        private boolean force = false;
        private CollectMacInterface l;

        public CollectRunnable(boolean forceResearch, CollectMacInterface listener)
        {
            this.force = forceResearch;
            this.l = listener;
        }

        @Override
        public void run()
        {
            l.onStart();
            if (force || !hasInit)
            {
                int res = collectMac();
                if (res > 0)
                {
                    hasInit = true;
                }
            }
            l.onFinish(res, ipAndMac, routeMac);
        }
    }

    public void stop()
    {
        unregister();
        threadPool.shutdownNow();
        threadPool = null;
        isCollectMac = false;
    }

    private void unregister()
    {
        if (mContext != null && receiver != null)
        {
            mContext.unregisterReceiver(receiver);
            receiver = null;
        }

    }

    int res = 0;

    // 获取本机ip,开启扫描;找到路由mac、本机mac;读取本机文件获取局域网mac;组装上传日志;确定后,退出app
    private int collectMac()
    {
        if (isCollectMac)
        {
            CollectMacLog.i(TAG, "collectMac(),do not need collect again   isCollectMac===true");
            res = Multiple_Call_ERROR;
            return res;
        }
        do
        {
            if (!isNeedCollectMac())
            {
                CollectMacLog.i(TAG, "collectMac(),isNeedCollectMac==false,so do not collect mac");
                res = Not_Need_ERROR;
                break;
            }
            if (!isConnected())
            {
                CollectMacLog.i(TAG, "collectMac(),net not connect,so do not collect mac");
                if (receiver == null)
                {
                    receiver = new NetBroadcastReceiver();
                    mContext.registerReceiver(receiver, new IntentFilter(
                            ConnectivityManager.CONNECTIVITY_ACTION));
                }
                res = Not_Connect_ERROR;
                break;
            }
            String localIp = getLocalIp();
            if (localIp == null || localIp.equals(""))
            {
                CollectMacLog.i(TAG, "collectMac(),local ip==null or '',so do not collect mac");
                res = Not_IP_ERROR;
                break;
            }
            String regex =
                    "(2[5][0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})\\.(25[0-5]|2[0-4]\\d|1\\d{2}|\\d{1,2})";
            if (!localIp.matches(regex))
            {
                CollectMacLog
                        .i(TAG, "collectMac(),local ip==" + localIp + ",so do not collect mac");
                res = IP_Format_ERROR;
                break;
            }

            try
            {
                pingLocal(localIp.substring(0, localIp.lastIndexOf(".")));
            } catch (IOException e)
            {
                e.printStackTrace();
                res = Not_Route_ERROR;
                break;
            } catch (InterruptedException e)
            {
                e.printStackTrace();
                res = Collect_Mac_IO_ERROR;
                break;
            }

            if (!isConnected())
            {
                CollectMacLog.i(TAG, "collectMac(),net not connect,so do not collect mac");
                if (receiver == null)
                {
                    receiver = new NetBroadcastReceiver();
                    mContext.registerReceiver(receiver, new IntentFilter(
                            ConnectivityManager.CONNECTIVITY_ACTION));
                }
                res = Not_Connect_ERROR;
                break;
            }
            boolean filter = filter(getMacs(), getRouteIp(localIp));
            if (!filter)
            {
                CollectMacLog.i(TAG, "collectMac(),filter==" + filter + ",so do not collect mac");
                res = Collect_Mac_Interrupt_ERROR;
                break;
            }
            isCollectMac = true;
            unregister();
            res = 1;
        } while (false);
        CollectMacLog.i(TAG, "collectMac(),collect mac is ok?:" + isCollectMac);
        return res;
    }


    /**
     * 循环ping 局域网内的ip地址
     * <p>
     * ping 太慢,改用arp 广播来实现。
     *
     * @param preIp 表示ip前三位,如172.20.139
     */
    private void pingLocal(String preIp) throws IOException, InterruptedException
    {
        String target_ip = "";
        for (int i = 0; i <= 255; i++)
        {
            target_ip = preIp + "." + i;
            if (i % 10 == 0)
            {
                CollectMacLog.i(TAG, "target ip == " + target_ip);
            }
            _ping(target_ip);
        }

        CollectMacLog.i(TAG, "ping finish");
    }

    byte[] REQ = {(byte) 0x28, (byte) 0x73, (byte) 0x65, (byte) 0x6e, (byte) 0x64,
            (byte) 0x20, (byte) 0x62, (byte) 0x79, (byte) 0x20, (byte) 0x74, (byte) 0x29};

    short UDP_PORT = 137;

    private void _ping(String target_ip)
    {
        if (target_ip == null || target_ip.equals("")) return;
        DatagramSocket socket = null;
        InetAddress address;
        DatagramPacket packet;
        try
        {
            address = InetAddress.getByName(target_ip);
            packet = new DatagramPacket(REQ, REQ.length, address, UDP_PORT);
            socket = new DatagramSocket();
            socket.setSoTimeout(200);
            socket.send(packet);
            socket.close();
        } catch (SocketException se)
        {
        } catch (UnknownHostException e)
        {
        } catch (IOException e)
        {
        } finally
        {
            if (socket != null)
            {
                socket.close();
            }
        }
    }

    private boolean filter(HashMap<String, String> macs, String routeIp)
    {
        Iterator<Map.Entry<String, String>> iterator = macs.entrySet().iterator();
        while (iterator.hasNext())
        {
            Map.Entry<String, String> entry = iterator.next();
            ipAndMac.put(entry.getKey(), entry.getValue().replaceAll(":", ""));
            CollectMacLog.i(TAG, " ip = " + entry.getKey() + ",mac ==" + entry.getValue());
        }
        if (macs.containsKey(routeIp))
        {
            routeMac = macs.get(routeIp).replaceAll(":", "");
        }
        return true;
    }

    /**
     * 是否需要收集,控制是否要收集
     */
    private boolean isNeedCollectMac()
    {
        //待考虑的策略
        return true;
    }

    private int getNetType()
    {
        ConnectivityManager connectivityManager =
                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo == null)
        {
            return -10;
        }
        return networkInfo.getType();
    }

    private boolean isConnected()
    {
        ConnectivityManager connectivityManager =
                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        if (networkInfo == null)
        {
            return false;
        }
        return networkInfo.isConnected();
    }

    /**
     * 获取本机ip
     */
    private String getLocalIp()
    {
        String localIp = "";
        try
        {
            // 获取本地设备的所有网络接口
            Enumeration<NetworkInterface> enumerationNi = NetworkInterface.getNetworkInterfaces();
            while (enumerationNi.hasMoreElements())
            {
                NetworkInterface networkInterface = enumerationNi.nextElement();
                String interfaceName = networkInterface.getDisplayName();
                String curType = (getNetType() == ConnectivityManager.TYPE_WIFI ? "wlan0" : "eth0");
                CollectMacLog.i(TAG, "网络名字" + interfaceName);
                if (curType.equals(interfaceName))
                {
                    Enumeration<InetAddress> enumIpAddr = networkInterface
                            .getInetAddresses();
                    while (enumIpAddr.hasMoreElements())
                    {
                        // 返回枚举集合中的下一个IP地址信息
                        InetAddress inetAddress = enumIpAddr.nextElement();
                        // 不是回环地址,并且是ipv4的地址
                        if (!inetAddress.isLoopbackAddress()
                                && inetAddress instanceof Inet4Address)
                        {
                            CollectMacLog.i(TAG, inetAddress.getHostAddress() + "   ");
                            localIp = inetAddress.getHostAddress();
                            return localIp;
                        }
                    }
                }
            }
        } catch (SocketException e)
        {
            e.printStackTrace();
        }
        return localIp;
    }

    /**
     * 获取路由Ip
     */
    private String getRouteIp(String localIp)
    {
        String routeIp = "";
        if (!isConnected())
        {
            return routeIp;
        }
        routeIp = localIp.substring(0, localIp.lastIndexOf(".")) + ".1";//默认
        if (getNetType() == ConnectivityManager.TYPE_WIFI)
        {
            WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            DhcpInfo info = wifiManager.getDhcpInfo();
            if (info != null)
            {
                long mask = info.gateway;
                routeIp = long2ip(mask);
                return routeIp;
            }
        }
        //有线情况下,通过读取文件
        File file = new File("/proc/net/route");
        FileInputStream fileInputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        try
        {
            fileInputStream = new FileInputStream(file);
            inputStreamReader = new InputStreamReader(fileInputStream);
            bufferedReader = new BufferedReader(inputStreamReader);
            String line = "";
            int index = 0;
            HashMap<Integer, String> routes = new HashMap<Integer, String>();
            while ((line = bufferedReader.readLine()) != null)
            {
                line = line.replaceAll("\\s{1,}", " ");
                routes.put(index, line);
                index++;
            }
            if (routes.size() > 2)
            {
                String routeIp16 = routes.get(1).split(" ")[2];
                if (routeIp16.length() == 8)
                {
                    StringBuffer stringBuffer = new StringBuffer();
                    stringBuffer.append(Integer.parseInt(routeIp16.substring(6, 8), 16));
                    stringBuffer.append(".");
                    stringBuffer.append(Integer.parseInt(routeIp16.substring(4, 6), 16));
                    stringBuffer.append(".");
                    stringBuffer.append(Integer.parseInt(routeIp16.substring(2, 4), 16));
                    stringBuffer.append(".");
                    stringBuffer.append(Integer.parseInt(routeIp16.substring(0, 2), 16));
                    routeIp = stringBuffer.toString();
                }
            }
        } catch (Exception e1)
        {
            e1.printStackTrace();
        } finally
        {
            try
            {
                if (bufferedReader != null)
                {
                    bufferedReader.close();
                    bufferedReader = null;
                }
                if (inputStreamReader != null)
                {
                    inputStreamReader.close();
                    inputStreamReader = null;
                }
                if (fileInputStream != null)
                {
                    fileInputStream.close();
                    fileInputStream = null;
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        return routeIp;
    }

    String long2ip(long ip)
    {
        StringBuffer sb = new StringBuffer();
        sb.append(String.valueOf((int) (ip & 0xff)));
        sb.append('.');
        sb.append(String.valueOf((int) ((ip >> 8) & 0xff)));
        sb.append('.');
        sb.append(String.valueOf((int) ((ip >> 16) & 0xff)));
        sb.append('.');
        sb.append(String.valueOf((int) ((ip >> 24) & 0xff)));
        return sb.toString();
    }

    /**
     * 获取mac
     */
    public HashMap<String, String> getMacs()
    {
        HashMap<String, String> ipMacs = new HashMap<String, String>();
        File file = new File("/proc/net/arp");
        FileInputStream fileInputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader bufferedReader = null;
        try
        {
            fileInputStream = new FileInputStream(file);
            inputStreamReader = new InputStreamReader(fileInputStream);
            bufferedReader = new BufferedReader(inputStreamReader);
            String line = "";
            while ((line = bufferedReader.readLine()) != null)
            {
                if (line.contains("IP"))
                {
                    continue;
                }
                line = line.replaceAll("\\s{1,}", " ");
                String[] items = line.split(" ");
                if (!"00:00:00:00:00:00".equals(items[3]))
                {
                    ipMacs.put(items[0], items[3]);
                }
            }
        } catch (FileNotFoundException e1)
        {
            e1.printStackTrace();
        } catch (IOException e1)
        {
            e1.printStackTrace();
        } finally
        {
            try
            {
                if (bufferedReader != null)
                {
                    bufferedReader.close();
                    bufferedReader = null;
                }
                if (inputStreamReader != null)
                {
                    inputStreamReader.close();
                    inputStreamReader = null;
                }
                if (fileInputStream != null)
                {
                    fileInputStream.close();
                    fileInputStream = null;
                }

            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return ipMacs;
    }

    private class NetBroadcastReceiver extends BroadcastReceiver
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            if (isConnected())
            {
                try
                {
                    if (threadPool == null || threadPool.isShutdown())
                    {
                        threadPool = Executors.newSingleThreadExecutor();
                    }
                    threadPool.submit(new CollectRunnable(isForceResearch, collectMacInterface));
                } catch (RejectedExecutionException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

}

 

import java.util.HashMap;
public interface CollectMacInterface
{
    /**
     * 开始执行相关逻辑
     */
    void onStart();

    /**
     * 执行完毕, resCode 表示结果,resCode>0,表示执行成功,resCode<0,表示各种异常
     * routeMac 路由器的mac地址
     * mac连接过路由的设备,列表里面包含本身的mac和路由器的mac。
     * 格式是没有“:”的
     */
    void onFinish(int resCode, HashMap<String,String> mac, String routeMac);

    final static int Multiple_Call_ERROR = -1;
    final static int Not_Need_ERROR = -2;
    final static int Not_Install_ERROR = -3;
    final static int Not_Connect_ERROR = -4;
    final static int Not_IP_ERROR = -5;
    final static int IP_Format_ERROR = -6;
    final static int Not_Route_ERROR = -7;
    final static int Collect_Mac_IO_ERROR = -8;
    final static int Collect_Mac_Interrupt_ERROR = -9;


}

 

         

posted @ 2018-04-17 16:42  忙里偷闲  阅读(770)  评论(0编辑  收藏  举报
广东财富东方律师事务所