简体   繁体   中英

Listing of the Network Devices in Android

Similar or the same Question has been answered here

I am creating an Android App, which sends a broadcast message to the network and prepares a list of devices responding back.

Now What I did:

I created an Activity Class DeviceManagerWindow.java which calls a thread Sender.java . Sender.java is responsible for sending the broadcast message.

Then the DeviceManagerWindow.java calls another thread which is responsible for listening to the devices responding back. The devices responding back will be listed in the Activity as soon as the device responds back. For that I have a TableLayout named deviceList .

What code I have written:

DeviceManagerWindow.java This method is called when a button for search is pressed

public void searchDevice(View v) throws IOException, InterruptedException
{
    //Log.v("TableLayout:",view.toString());
    sendMulticastFlyport = new Thread(new FlyportSender(MAC));
    sendMulticastFlyport.start();
    new Thread()
    {
        public void run()
        {
            MulticastSocket socketComputer=null;
            try
            {
                socketComputer = new MulticastSocket(WifiConstants.COMPUTER_RECV_PORT);
                socketComputer.joinGroup(InetAddress.getByName(WifiConstants.COMPUTER_NETWORK_ADDR));
                socketComputer.setSoTimeout(1*60*1000);
                byte[] inBufComputer = new byte[1024];
                DatagramPacket inPacketComputer = new DatagramPacket(inBufComputer, inBufComputer.length);

                while(true)
                {
                    System.out.println("Listening...");
                    socketComputer.receive(inPacketComputer);
                    System.out.println("Received");
                    String msg = new String(inBufComputer, 0, inPacketComputer.getLength());
                    DeviceInformation device = new DeviceInformation(1, msg, inPacketComputer.getAddress().toString());

                    addDevice(device, false, 1);

                    Log.v("Received:","Received Computer From :" + inPacketComputer.getAddress() + " Msg : " + msg);
                    //System.out.write(inPacket.getData(),0,inPacket.getLength());
                    System.out.println();
                    Thread.sleep(2000);
                }
            }
            catch(Exception e)
            {
                Log.v("Exception:","During Receiving Computer: "+e.toString());
                try
                {
                    addDevice(null, true, 1);
                }
                catch (IOException e1)
                {
                    Log.v("Exception:", "Computer End Error: " +e1);
                }
            }
            finally
            {
                socketComputer.close();
            }
        }
    }.start();

The following code creates a list:

public void addDevice(DeviceInformation device, boolean bool, int type) throws IOException
{
    TableLayout tb = (TableLayout) findViewById(R.id.DeviceList);
    Log.v("addDevice","Called");
    if(bool)
    {
        LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        TableRow tr = new TableRow(getApplicationContext());
        TextView tv = new TextView(getApplicationContext());
        System.out.println(tb);
        tv.setLayoutParams(layout);
        tr.setLayoutParams(layout);
        String message;
        Log.v("addDevice","Device Timeout");
        switch(type)
        {
            case 1:
                computerEnd=true;
                break;
            case 2:
                raspberryEnd=true;
                break;
            case 3:
                flyportEnd=true;
                break;
        }
        if(computerEnd && raspberryEnd && flyportEnd)
        {
            if(rowCounter>0)
            {
                message = "No More Devices";
            }
            else
            {
                message = "No Devices Found"; 
            }
            tv.setText(message);
            tv.setTextColor(Color.WHITE);
            if(rowCounter%2==0)
            {
                tr.setBackgroundColor(Color.DKGRAY);
            }
            else
            {
                tr.setBackgroundColor(Color.GRAY);
            }
            tv.setVisibility(1);
            tr.addView(tv);
            tb.addView(tr);
        }
    }
    else
    {   
        LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        TableRow tr = new TableRow(getApplicationContext());
        TextView tv = new TextView(getApplicationContext());

        tv.setLayoutParams(layout);
        tr.setLayoutParams(layout);

        Log.v("addDevice","Received");
        String textToDisplay = device.getDeviceTypeString()+"\n"+device.getIPAddress(); //Write the text to display
        tv.setText(textToDisplay);
        tv.setTextColor(Color.WHITE);
        Drawable img;
        if(device.getDeviceType()==1)
        {
            img = getApplicationContext().getResources().getDrawable(R.drawable.pc);
        }
        else if(device.getDeviceType()==2)
        {
            img = getApplicationContext().getResources().getDrawable(R.drawable.raspberry);
        }
        else
        {
            img = getApplicationContext().getResources().getDrawable(R.drawable.flyport);
        }
        img.setBounds(0,0,70,45);
        tv.setCompoundDrawables(null, null, img, null);
        tv.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {

            }
        });
        if(rowCounter%2==0)
        {
            tr.setBackgroundColor(Color.DKGRAY);
        }
        else
        {
            tr.setBackgroundColor(Color.GRAY);
        }
        rowCounter++;
        Log.v("Result","Device Added");
    }
}

Now it is showing me an error in the logCat as:

05-11 22:01:10.165: E/AndroidRuntime(13873): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

What I have figured out from this is only the UIThread is allowed to access the Views that is created.

Previously I had tried:

new Thread()
{
    public void run()
    {
        runOnUiThread(){
        MulticastSocket socketComputer=null;
        try
        {
            ....        
            ....
            ....
    }
}

And that time I received an error:

Main thread cannot access Network

Before that I had tried to use synchronized methods which was called from the Receiving.java Thread File. but It also gave an error of not creating the list.

I have tried all possible ways.

Now what whould I do.?

You figured it out right. Now you can learn to either use a Handler to pass information to the UI thread (see http://www.techotopia.com/index.php/A_Basic_Overview_of_Android_Threads_and_Thread_handlers ) or AsyncTask (see http://developer.android.com/reference/android/os/AsyncTask.html ).

I personally prefer AsyncTask. You can paste the code which performs the search into the doInBackground() method (not need to use a separate thread, doInBackground() already does that for you) and paste the UI-related code (the list creation code) into the onPostExecute() method. Search for further examples of AsyncTask if it is not sufficiently clear how it works from the link.

EDIT: If you intend your device search code to run indefinitely, then you have to resort to Handler, as AsyncTask expects the doInBackground() method to finish before running onPostExecute(). See which option better suits your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM