Monday, December 21, 2015

Get HostName of WiFi hotspot clients, and check if it is still connected.


Previous posts show how to "Retrieve IP and MAC addresses from /proc/net/arp" and "Lookup manufacturer/vendor info from MAC address". This post show how to get the Host Name of the connected clients.

It can be noted that if we call getCanonicalHostName() or getHostName() methods of the InetAddressobjects, it will return  the IP address. If we call getLocalHost().getCanonicalHostName() or getLocalHost().getHostName() methods, it will return the host name, "localhost".

Also, if a devices disconnected, the file /proc/net/arp will not updated immediately. We can determine if it is still connected by calling inetAddress.isReachable(timeout). If false returned, means it is disconnected.

MainActivity.java
package com.blogspot.android_er.androidlistclient;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    Button btnRead;
    TextView textResult;

    ListView listViewNode;
    ArrayList<Node> listNote;
    ArrayAdapter<Node> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnRead = (Button)findViewById(R.id.readclient);
        textResult = (TextView)findViewById(R.id.result);

        listViewNode = (ListView)findViewById(R.id.nodelist);
        listNote = new ArrayList<>();
        ArrayAdapter<Node> adapter =
                new ArrayAdapter<Node>(
                        MainActivity.this,
                        android.R.layout.simple_list_item_1,
                        listNote);
        listViewNode.setAdapter(adapter);

        btnRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new TaskReadAddresses(listNote, listViewNode).execute();
            }
        });
    }

    class Node {
        String ip;
        String mac;
        String CanonicalHostName;
        String HostName;
        String LocalHostCanonicalHostName;
        String LocalHostHostName;
        String remark;
        boolean isReachable;

        Node(String ip, String mac){
            this.ip = ip;
            this.mac = mac;
            queryHost();
        }

        @Override
        public String toString() {
            return "IP: " + ip + "\n" +
                    "MAC: " + mac + "\n" +
                    "CanonicalHostName:\t" + CanonicalHostName + "\n" +
                    "HostName:\t" + HostName + "\n" +
                    "getLocalHost().getCanonicalHostName():\t" + LocalHostCanonicalHostName + "\n" +
                    "getLocalHost().getHostName():\t" + LocalHostHostName + "\n" +
                    "isReachable: " + isReachable +
                    "\n" + remark;
        }

        private void queryHost(){
            try {
                InetAddress inetAddress = InetAddress.getByName(ip);
                CanonicalHostName = inetAddress.getCanonicalHostName();
                HostName = inetAddress.getHostName();
                LocalHostCanonicalHostName = inetAddress.getLocalHost().getCanonicalHostName();
                LocalHostHostName = inetAddress.getLocalHost().getHostName();
                isReachable = inetAddress.isReachable(3000);

            } catch (UnknownHostException e) {
                e.printStackTrace();
                remark = e.getMessage();
            } catch (IOException e) {
                e.printStackTrace();
                remark = e.getMessage();
            }
        }
    }

    private class TaskReadAddresses extends AsyncTask<Void, Node, Void> {

        ArrayList<Node> array;
        ListView listView;

        TaskReadAddresses(ArrayList<Node> array, ListView v){
            listView = v;
            this.array = array;
            array.clear();
            textResult.setText("querying...");
        }

        @Override
        protected Void doInBackground(Void... params) {
            readAddresses();
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            textResult.setText("Done");
        }

        @Override
        protected void onProgressUpdate(Node... values) {
            listNote.add(values[0]);
            ((ArrayAdapter)(listView.getAdapter())).notifyDataSetChanged();
        }

        private void readAddresses() {
            BufferedReader bufferedReader = null;

            try {
                bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));

                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    String[] splitted = line.split(" +");
                    if (splitted != null && splitted.length >= 4) {
                        String ip = splitted[0];
                        String mac = splitted[3];
                        if (mac.matches("..:..:..:..:..:..")) {
                            Node thisNode = new Node(ip, mac);
                            publishProgress(thisNode);
                        }
                    }
                }

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally{
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}



2 comments:

yassine said...

Salut, vous plait lors de la compilation un problème arrivera concernant les champs de formulaire TextView, Button et surtout ListView
Pourquoi et qu'il est la solution??
Merçi d'avance

Unknown said...

Hmm, smth strange. isReachable always returns false. What to do?