简体   繁体   中英

Android handler only sends one message

I am trying to implement a REST interface in android and I need a Thread in the background sending "I am alive" messages to an ip address. To do so I created a Thread Called RestPostThread that runs in the background while I do stuff in my UI thread.

The problem is that after sending the first message to the RestPostThread I can't quit the looper or send a different message to it with another IP or something.

Here are the code for both the UI and the RestPostThread:

public class MainActivity extends AppCompatActivity{

Handler workerThreadHandler;


protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    final TextView text1 = (TextView) findViewById(R.id.text1);
    final TextView text2 = (TextView) findViewById(R.id.text2);
    setSupportActionBar(toolbar);


    final RestPostThread RPT = new RestPostThread();
    RPT.start();

    while(workerThreadHandler == null ) {
        workerThreadHandler = RPT.getThreadHandler();
    }

    Button buttonStop = (Button) findViewById(R.id.buttonStop);
    buttonStop.setOnClickListener(new View.OnClickListener(){
        public void onClick(View view) {
            try {



                workerThreadHandler.getLooper().quit();
            }catch(Exception e){
                text1.setText(e.getMessage());
                text2.setText( "Exception!");
            }

        }
    });

    Button buttonSend = (Button) findViewById(R.id.buttonSend);
    buttonSend.setOnClickListener(new View.OnClickListener(){
        public void onClick(View view) {
            try {
                text1.setText(new RestGet().execute(editText.getText().toString()).get());
                text2.setText("everything went well!");
            }catch(Exception e){
                text1.setText(e.getMessage());
                text2.setText( "Exception!");
            }

        }
    });
}

And here is the code for the RestPostThread:

public class RestPostThread extends Thread  {
public Handler mHandler;

@Override
public void run(){

    Looper.prepare();
    mHandler = new Handler() {
        public void handleMessage(Message msg) {
            Log.d("MYASDASDPOASODAPO", "dentro mensaje");
            while (!msg.obj.equals(null)) {
                try {
                    Thread.sleep(1000);
                    URL url = new URL(msg.obj.toString());
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setDoOutput(true);
                    conn.setRequestMethod("POST");
                    String input = "<Instruction><type>put_me_in</type><room>Room 1</room></Instruction>";

                    OutputStream os = conn.getOutputStream();
                    os.write(input.getBytes());
                    os.flush();

                    if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
                        //  throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
                    }
                    BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
                    String output;
                    String aux = new String();
                    while ((output = br.readLine()) != null) {
                        aux = aux + output;
                    }
                    conn.disconnect();
                    //return aux;
                } catch(MalformedURLException e) {
                    e.printStackTrace();
                    //return null;
                } catch(IOException e) {
                    e.printStackTrace();
                    //return null;
                } catch(Exception e) {
                }
            }
            Log.d("CLOSING MESSAGE", "Closing thread");
        }
    };
    Looper.loop();
}

public Handler getThreadHandler() {
    return this.mHandler;
}

Have a look at HandlerThread for dealing with a thread to handle just messages. Your Handler should not loop on a message like that, it won't work. It's the Looper 's job to deal with new, incoming Message or Runnable objects sent to the Handler which is bound to the Looper .

Regardless, you should take a closer look at using a Loader to handle REST type APIs; or, explore a 3rd party library, such as retrofit, for dealing with REST.

I managed to solve the issue. The problem was that I was wrapping everything inside this:

while (!msg.obj.equals(null)) {}

I implemented handlers in both this thread and the UI thread and now I have communication back and forth between the both, my RestPostThread looks like this now:

public class RestPostThread extends Thread  {

public Handler mHandler,uiHandler;


public RestPostThread(Handler handler) {
    uiHandler = handler;
}

@Override
public void run(){
    Looper.prepare();
    mHandler = new Handler() {
        public void handleMessage(Message msg) {
                try {
                    //Thread.sleep(1000);
                    URL url = new URL(msg.obj.toString());
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setDoOutput(true);
                    conn.setRequestMethod("POST");
                    String input = "<Instruction><type>put_me_in</type><room>Room 1</room></Instruction>";

                    OutputStream os = conn.getOutputStream();
                    os.write(input.getBytes());
                    os.flush();

                    if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
                        //  throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
                    }
                    BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
                    String output;
                    String aux = new String();
                    while ((output = br.readLine()) != null) {
                        aux = aux + output;
                    }
                    conn.disconnect();
                    Message msg2 = uiHandler.obtainMessage();
                    msg2.obj = aux;
                    uiHandler.sendMessage(msg2);
                }catch(MalformedURLException e){
                    e.printStackTrace();
                }catch(IOException e){
                    e.printStackTrace();
                }catch(Exception e){
                }
            }
    };
    Looper.loop();
}


public Handler getThreadHandler() {
    return this.mHandler;
}

}

And in my MainActivity I have this handler that allows me to "loop" (basically is just going back and forth between the RestPostThread and the UIThread) my Post message until I decide to stop from the MainActivity changing the boolean loop:

 public Handler uiHandler = new Handler() {
    public void handleMessage(Message inputMessage) {
        Log.d("FROM UI THREAD",inputMessage.obj.toString());
        if(loop) {
            Message msg = workerThreadHandler.obtainMessage();
            String url = "http://192.168.1.224:9000/xml/android_reply";
            msg.obj = url;
            workerThreadHandler.sendMessageDelayed(msg,1000);
        }
    }
};

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