0

In my application i have byte array of 12 digit which is used to read the status. After writing this array i am getting the status of different buttons. Based on this response i am setting up my buttons to ON|OFF. i am doing this task repeatedly.if i set this interval time too less i.e 100ms and pressing those buttons too frequently then my application is stops to respond.

Here is the code snippet.

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);         
    getSharedSettings();

    fanDimmer1=(ToggleButton)findViewById(R.id.button_fan1);
    fanDimmer2=(ToggleButton)findViewById(R.id.button_fan2);
    dimmerLight1=(ToggleButton)findViewById(R.id.button_light1);
    dimmerLight2=(ToggleButton)findViewById(R.id.button_light2);


    fanDimmer1.setOnClickListener(this);
    fanDimmer2.setOnClickListener(this);
    dimmerLight1.setOnClickListener(this);
    dimmerLight2.setOnClickListener(this);

    if(ip.equals("") || port.equals(""))
    {
        new AlertDialog.Builder(MainActivity.this)
        .setTitle("Warning !")
        .setMessage("Please set IP and PORT first")
        .setIcon(android.R.drawable.ic_dialog_alert)
        .setNeutralButton("ok", null)
        .show();
    }
    else
    {
        new Thread(new Runnable() 
        {   
            @Override
            public void run()
            {
                Log.v(TAG, "openconnection");
                openConnection();
            }
        }).start();
        m_handler = new Handler();
        startRepeatingTask();

    }

}

public void openConnection()
{
    // TODO Auto-generated method stub
    try 
    {
        s = new Socket(ip, Integer.parseInt(port));
        i = s.getInputStream();
        iD = new DataInputStream(i);
        o = s.getOutputStream();
        oD = new DataOutputStream(o);
        Log.v(TAG, "openconnection 2");

    }
    catch (UnknownHostException e) {
        // TODO: handle exception
        Log.v("UnknowHostException :::::", "In Catch Block");
        e.printStackTrace();
    }
    catch (IOException e) {
        // TODO: handle exception
        Log.v("IOException :::::", "In Catch Block");
        e.printStackTrace();
    }
}

Runnable m_statusChecker = new Runnable() 
{
    @Override
    public void run() 
    {
        updateStatus();
        m_handler.postDelayed(m_statusChecker,100);
    }

    private void updateStatus() 
    {
        // TODO Auto-generated method stub
        Log.v("test", "1");
        try {
            byte[] data1 = new byte[1024], packet1 = 
                { 
                    (byte) 0x00,(byte) 0x00,(byte) 0x00, 
                    (byte) 0x00,(byte) 0x00,(byte) 0x06, 
                    (byte) 0x01,(byte) 0x01,(byte) 0x00,
                    (byte) 0x00,(byte) 0x00,(byte) 0x19
                };

            o.write(packet1);
            i.read(data1, 0, 1024);

            byte_to_hex = ConversionMethods.bytesToHex(data1).substring(18, 26);
            char[] arr = byte_to_hex.toCharArray();
            for (int i = 0; i < arr.length - 1; i += 2) 
            {
                char temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
            }

            swapped_result=new String(arr);
            result = ConversionMethods.hexStringToNBitBinary(swapped_result, 32);

            int counter = 0;
            for( int i=0; i<result.length(); i++ ) 
            {
                if( result.charAt(i) == '1' )
                {
                    counter++;        
                }  
            }
            status=Integer.toString(counter);
            txt_status.setText(status);
            Log.v(TAG, "status is ::"+status);


            char[] c=result.toCharArray();
            int count=0;
            for (int i=0;i<result.length();i++)
            {
                count++;
                char j=c[i];
                //Log.v(TAG, count+"::"+j);
                if(count==1)
                    toggleButton=dimmerLight1;
                else if(count==2)
                    toggleButton=fanDimmer2;
                else if(count==3)
                    toggleButton=fanDimmer1;
                else if(count==4)
                    Log.v(TAG, "Count 4 is 0");

                if(j=='1')
                    toggleButton.setChecked(true);
                else
                    toggleButton.setChecked(false); 
            }

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
};

void startRepeatingTask() {
    m_statusChecker.run();
}

void stopRepeatingTask() {
    m_handler.removeCallbacks(m_statusChecker);
}

And on button click i am doing this:

@Override
public void onClick(View v) 
{

    if(v.equals(fanDimmer1))
    {
        if (fanDimmer1.isChecked()) 
        {
            Toast.makeText(MainActivity.this, "Fan 1 is ON", Toast.LENGTH_SHORT).show();
            setByteArray((byte) 0x01, (byte) 0xff);
        } else 
        {
            Toast.makeText(MainActivity.this, "Fan 1 is OFF", Toast.LENGTH_SHORT).show();
            setByteArray((byte) 0x01, (byte) 0x00);
        }
    }

}

here is setByteArray() method i have 24 this type of buttons.

Any advice and suggestion will be appreciated.
Thanks

Juned
  • 6,290
  • 7
  • 45
  • 93

1 Answers1

1

You are calling startRepeatingTask() from your main thread:

void startRepeatingTask() {
   m_statusChecker.run();
}

This means that your statusChecker will runs in the main thread too.

  • The first thing to do is to update the code of your updateStatus method and use mHandler to post ONLY ui-update code to the main UI-thread

  • Next you have to run the statusChecker in another thread

To do it, you have (at least) two options :

  1. [The complex way] Do your own thread management and write something like this in your startRepeatingTask

    void startRepeatingTask() { new Thread(m_statusChecker).start(); }

    adapt the stop method (i.e. use a monitor, an infinite loop and a sleep)

  2. [The smart way] Take a look at Timer and TimerTask (and this) from the Android API and use them to implement what you need.

EDIT

Focus on this code:

for (int i=0;i<result.length();i++)
        {
            count++;
            char j=c[i];
            //Log.v(TAG, count+"::"+j);
            if(count==1)
                toggleButton=dimmerLight1;
            else if(count==2)
                toggleButton=fanDimmer2;
            else if(count==3)
                toggleButton=fanDimmer1;
            else if(count==4)
                Log.v(TAG, "Count 4 is 0");

            if(j=='1')
                toggleButton.setChecked(true);
            else
                toggleButton.setChecked(false); 
        }

The effect of this loop will be:

  • iteration 0 (if any) : dimmerLight1 will be checked or unchecked
  • iteration 1 (if any) : fanDimmer2 will be checked or unchecked
  • iteration 2 (if any) : fanDimmer1 will be checked or unchecked
  • iteration 3 (if any) : fanDimmer1 will be checked or unchecked
  • iteration 4 (if any) : fanDimmer1 will be checked or unchecked
  • iteration 5 (if any) : fanDimmer1 will be checked or unchecked
  • ... (fanDimmer1 will be check or unchecked until the end of loop)

I'm pretty sure this not what you need. (except if result.size() is always 3, but in any other situation: this code will produce weird things)

You can do something like this:

//assuming buttons is a ToggleButton[32] populated with all your buttons in the correct order
for (int i=0;i<result.length();i++)
    {
        buttons[i].setChecked(c[i]=='1'); 
    }
Community
  • 1
  • 1
ben75
  • 29,217
  • 10
  • 88
  • 134
  • Earlier i was using timer to get updated values and to update UI i used `runOnUiThread` method, but i wasn't succeeded to get desired result. so after that i have changed my code to this – Juned Jan 22 '13 at 11:46
  • runOnUiThread is the way to go. Be sure to use it only for ui updates : `txt_status.setText(status);` and `toggleButton.setChecked(...);` – ben75 Jan 22 '13 at 11:49
  • yeah i used that method only for UI updates but don't know why my toggle buttons got blinked sometimes when i was toggling on|off too frequently. – Juned Jan 22 '13 at 11:53
  • You are updating the state of your toggleButton in a strange way... I don't understand what you are trying to do... but it seems that your code can check/uncheck the same toggle button in 2 successive iteration. So I suggest you to double-check the code of your loop `for (int i=0;i – ben75 Jan 22 '13 at 12:01
  • yeah,you got it perfectly toggle buttons are got checked and unchecked in 2 successive iteration 1) when user toggles on|off and 2) each time when response comes from `m_statusChecker` method. how do i avoid this ? – Juned Jan 22 '13 at 12:22
  • why i am doing this ? so this is the scenario. in response i am getting string and its length is fixed to 32 character and each character represents the status of specific button. so i am reading each character and setting them to ON or oFF. what is the other option to implement this thing ? – Juned Jan 22 '13 at 12:55
  • @juned ok but your code is only updating 3 buttons: toggleButton will never something else than dimmerLight1 or fanDimmer2 or fanDimmer1. You must put your 32 buttons in an array and get the button to toggle in that array. – ben75 Jan 22 '13 at 13:05
  • yeah i know that, for simplicity i have posted my code only with for buttons but in actually i am reading all 32 elements of result and setting toggle buttons. but my actual problem is application is freezing if i am doing too much read/write on sockets. so i want to create some different class which may implements runnable to get updated status of this buttons, but not getting anyway to implement this :( – Juned Jan 22 '13 at 13:19