8

I want to display a toast once the message is sent to a socket.After this "Log.d("ClientActivity", "C: Sent.");"

Whether I need to create a separate thread to display Toast?

public class ClientActivity extends Activity {
private Handler handler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.client);
    serverIp = (EditText) findViewById(R.id.EditText01);
    message =(EditText) findViewById(R.id.EditText02);
    connectPhones = (Button) findViewById(R.id.Button01);

}

    public void Click1(View v) {
        if (!connected) {
            serverIpAddress = serverIp.getText().toString();
            if (!serverIpAddress.equals("")) {
                Thread cThread = new Thread(new ClientThread());
                cThread.start();
            }
        }
    }


private class ClientThread implements Runnable {

    public void run() {
        try {
            InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
            Log.d("ClientActivity", "C: Connecting...");
            Socket socket = new Socket(serverAddr, ServerActivity.SERVERPORT);
            connected = true;
            while (connected) {
                try {
                    if(i>5)
                    {


                    } 
                    else
                    {   
                        Log.d("ClientActivity", "C: Sending command.");
                        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                                .getOutputStream())), true);
                        // where you issue the commands
                        message1= message.getText().toString();
                        out.println(message1);
                        i=i+1;
                        Log.d("ClientActivity", "C: Sent.");
                    }    
                } catch (Exception e) {
                    Log.e("ClientActivity", "S: Error", e);
                }
            }
            socket.close();
            Log.d("ClientActivity", "C: Closed.");
        } catch (Exception e) {
            Log.e("ClientActivity", "C: Error", e);
            connected = false;
        }
    }
}

}

Shan
  • 2,822
  • 9
  • 40
  • 61

4 Answers4

22

put

  runOnUiThread(new Runnable() {
                 public void run() {

                     Toast.makeText(ClientActivity.this,"asdf",Toast.LENGTH_LONG).show();
                }
            });

after this line

  Log.d("ClientActivity", "C: Connecting...");
5hssba
  • 8,079
  • 2
  • 33
  • 35
  • It still throws a error message "The method makeText(Context, CharSequence, int) in the type Toast is not applicable for the arguments (new Runnable(){}, String, int)" – Shan May 16 '12 at 02:03
  • 1
    @Shan you are probably passing the wrong context. Double check that you are passing the proper context and not just 'this'. – SoundsDangerous May 05 '14 at 18:55
  • For future reference: When calling the toast from inside a runnable, ALWAYS write ActivityName.this, or explicitly imply a context(from a class outside the activity for an instance).Just writing "this" makes Android(and Android Studio) think you are referring to the Runnable, and not the activity(and thus not the context). It is the same as when you are in a nested class: calling "this" doesn't refer to the activity the nested class is in; it refers to the nested class and thus not the context. It is the same with the Runnable. – Zoe Apr 09 '17 at 19:22
3
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        System.out.println("I'm in handler");
        Toast.makeText(YourActivity.this, "This is a toast", Toast.LENGTH_SHORT).show(); 
    }
}, 1000);             
ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253
itechDroid
  • 1,031
  • 1
  • 11
  • 17
  • 1
    If the context is an Activity (as you've implied with YourActivity.this) you can just use runOnUiThread(), right? – David Doria Oct 03 '13 at 14:08
  • @DavidDoria you are right, as handler is only use to do any ui changes and when you see runOnUiThread method implementation, it first check current thread is ui thread or not and if current thread is not ui thread then it do given task in handler. – itechDroid Oct 04 '13 at 07:12
3

You cannot create a toast from inside a thread. Because this new thread does not have access to the getApplicationContext() that you pass on to it. You somehow have to establesh a communication with the UI thread(i.e the main thread).
So whenever you want to toast something do it in the handler.Post(Runnable) method. Handler is the middle man between the UI thread and the separate thread that you are running. All UI Operations will have to be done in handler.Post(Runnable)'s run() method.

So in your activity to display a toast do this :

private class ClientThread implements Runnable {

    public void run() {
        try {
            InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
             .....
             .....
              message1= message.getText().toString();
                        out.println(message1);
                        i=i+1;
                        Log.d("ClientActivity", "C: Sent.");
                        handler.post(new Runnable(){
                          public void run()
                          {
                             Toast.make(....);
                           }
                         });

Don't forget to declare and initialize a handler object in your main activity(outside the thread)

handler=new Handler();
Ashwin
  • 12,691
  • 31
  • 118
  • 190
1

Declare a global Handler first,

Handler handler=null;

Then Create a handler in your onCreate() like this,

Handler handler=new Handler()
{
  public void handleMessage(Message msg)
{
  if(msg.what==0)
{
   Toast.makeText(ClientActivity.this,"Your Toast Mesage Goes here",Toast.LENGTH_LONG).show();
}

}
};

And now in your Runnable class add this line after "Log.d("ClientActivity", "C: Sent.");"

handler.sendEmptyMessage(0);

The problem you are facing is because you can't update UI from runnable. Handlers connect you to your main UI. So you have to pass a message to your handler from your Runnable.

Andro Selva
  • 53,910
  • 52
  • 193
  • 240