1

I want to display a message when data from client is received. I started a server and a client. Client sends and receives confirmation from server, but on server side android, wasn't displayed any message, and app crashed, and here I paste what i got from log cat. and also inner class, when i want to show message:

import android.widget.Toast;

class Handler implements Runnable { 
    private Context myContext; 

    private static final String TAG = "myLogs";

    public Handler(Socket client) { 
        this.client = client; 
    } 
    public Handler(final Context context) { 
        this.myContext= context; 
    } 

    public void run() { 
        try {
            //message received..

            Toast.makeText(myContext.getApplicationContext(), "msg msg", Toast.LENGTH_SHORT).show();
            Log.d(TAG, "received....");
        } catch (IOException e) { 
            System.out.println("Errore: " + e); 
        } 
    } 
} 

Logcat

   04-29 17:21:53.679: D/My log(19533): waiting for connnections   
   04-29 17:24:13.726: D/My Log(19533): Connected     04-29
   17:24:14.859:W/dalvikvm(19533): threadid=9: thread exiting with uncaught exception    (group=0x40018578)     04-29 17:24:14.859: E/AndroidRuntime(19533): FATAL EXCEPTION: Thread-10 04-29
   17:24:14.859: E/AndroidRuntime(19533): java.lang.NullPointerException     04-29
   17:24:14.859:E/AndroidRuntime(19533): at com.example.tcpserver.Handler.run(Handler.java:49)     04-29
   17:24:14.859: E/AndroidRuntime(19533): at java.lang.Thread.run(Thread.java:1019)
Phil
  • 35,852
  • 23
  • 123
  • 164
chajka
  • 51
  • 2
  • 4
  • 13

6 Answers6

3

There are two things wrong with your code. The first, as others have stated, is that you are calling the command from a non-ui thread. Although it is not evident from your code, the logcat suggests that you are calling this from a non-ui thread. In order to show a Toast message, you will need to ensure that you are calling the toast from within the UI thread.

The other issue is that you are attempting to show the Toast with the Application context. This will fail, because the application context cannot update the UI. Simply use the Activity context.

Your call for creating the Toast should be modified to look like this:

myContext.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(myContext, "msg msg", Toast.LENGTH_SHORT).show();
    }
});
Phil
  • 35,852
  • 23
  • 123
  • 164
  • this class implements Runnable (class Handler implements Runnable { ) and i am calling it inside run() , so i am in ui thread or not? i am confused. – chajka Apr 29 '13 at 15:19
  • @chajka, You need to place this block of code inside of your `run()` method. Your `Handler` class is running on a separate thread. `run` is overridden by all classes that `implement Runnable` or `extend Thread`, so you will see it a lot in development. – Phil Apr 29 '13 at 15:23
  • can i place it after public void run(){ try{ //send //receive//here – chajka Apr 29 '13 at 15:30
  • then it's asking to add cast to mycontext ((Object) myContext).runOnUiThread(new Runnable() {, do i need this? – chajka Apr 29 '13 at 15:33
  • @chajka, place it at `run(){ try { //here }catch(Exception e){} }`. As for the cast - you may need to cast it to an `Activity` (is `new Handler(this)` called from your Activity)? – Phil Apr 29 '13 at 15:46
  • class Handler implements Runnable { .... private Context myContext; public Handler(Socket client) { this.client = client; } public Handler(final Context context) { this.myContext= context; } public void run() { try {myContext.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(myContext, "msg msg", Toast.LENGTH_SHORT).show(); } }); } catch (IOException e) { System.out.println("Errore: " + e); } } } – chajka Apr 29 '13 at 15:54
  • from main i'm calling class server and from server i am calling this class – chajka Apr 29 '13 at 15:55
  • The method runOnUiThread(new Runnable(){}) is undefined for the type Context – chajka Apr 29 '13 at 16:06
  • @chajka, `runOnUiThread` is a method that is available to `Activities`. You need to have access to the `Activity Context` to use it. When you create your main `Activity`, call `Handler myHandler = new Handler(this)`. Then your `myContext` Object will be of type `Activity` - so you can do the cast: `((Activity) context)`. – Phil Apr 29 '13 at 16:38
  • @chajka, see my other answer. Since you provided more complete code, it is definitely a design flaw. Check out my recommendation for a new constructor. This will solve the issue. – Phil Apr 29 '13 at 16:49
0

You cannot show toast inside a thread that is not the main GUI thread.

It seems that you chose "Handler" as the name for the class you're writting. You should use a android.os.Handler to make this inside the GUI thread, not yours.

Also, it seems that you get a NullPointerException in your code. Can you tell us on which line it does occur ? (Edit : which line is "Handler.java:49" in your code)

Orabîg
  • 11,718
  • 6
  • 38
  • 58
  • yes, handler it's class i am writing it in(totally i have 3 classes, main, server, and handler), could u give some example, cause i don't understand what is GUI thread.. i am not sure i know in which line i got it, where can i check it? – chajka Apr 29 '13 at 14:48
  • It says Handler.java line 49. – marcantonio Apr 29 '13 at 14:50
  • 1
    Reading http://developer.android.com/guide/components/processes-and-threads.html and http://stackoverflow.com/questions/3652560/what-is-the-android-uithread-ui-thread should be very helpful (mandatory indeed) – Orabîg Apr 29 '13 at 14:52
  • line 49 :Toast.makeText(myContext.getApplicationContext(), "msg msg", Toast.LENGTH_SHORT).show(); – chajka Apr 29 '13 at 14:53
  • Then split this line (1:`text=makeText(...)`, 2:`text.show()`) then identify which one gives a NPE – Orabîg Apr 29 '13 at 14:54
  • thx, i am going to read all your links. i will be back if i will have questions) – chajka Apr 29 '13 at 14:59
0

You can only display toasts from the UI thread. Trying it from another thread will cause a crash. Have a look at Handlers, Handler.Callbacks and Messages.

HTH, Marc

marcantonio
  • 958
  • 10
  • 24
0

After seeing more complete code, it is obvious that the design of this class has some major issues. The most obvious is that it has two constructors that take in different Objects, and ignore the other ones. Thus, there will either be a null socket, or a null context.

Second, as I posted in my other answer, there are some flaws with how the Toast is shown.

I propose you make some core changes to this class. For starts, remove your constructors and add this instead:

public Handler(Activity context, Socket client) { 
    this.client = client; 
    this.myContext= context; 
}

Now you can construct one instance and not worry about having null Objects. This also enforces you to construct this with Activity context - so you can call the method unOnUiThread, so now you can call:

((Activity) myContext).runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(myContext, "msg msg", Toast.LENGTH_SHORT).show();
    }
});
Phil
  • 35,852
  • 23
  • 123
  • 164
  • thx, a lot, but i got error again 04-29 20:42:34.640: E/AndroidRuntime(23347): FATAL EXCEPTION: Thread-10 04-29 20:42:34.640: E/AndroidRuntime(23347): java.lang.NullPointerException 04-29 20:42:34.640: E/AndroidRuntime(23347): at com.example.tcpserver.Handler.run(Handler.java:54) 04-29 20:42:34.640: E/AndroidRuntime(23347): at java.lang.Thread.run(Thread.java:1019) , it's this line ((Activity) myContext).runOnUiThread(new Runnable() { – chajka Apr 29 '13 at 17:46
  • @chajka, glad I could help. As for what the error is - you can debug a lot with print statements. Add this to your constructor: `Log.d("Handler", "Context is " + context == null ? "null. Socket is " : "not null. Socket is " + socket == null ? "null." : "not null.";` You can also try step-by-step debugging by adding a *breakpoint* to that line of code. [More about debugging](http://stackoverflow.com/questions/8551818/how-to-debug-android-application-line-by-line-using-eclipse) – Phil Apr 29 '13 at 18:13
0

I had the same problem. When I invoked the code on UI thread the issue resolved for me

public void showToastMessage(final String msg) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(BaseActivity.this, msg, Toast.LENGTH_LONG).show();
        }
mujeeb
  • 799
  • 5
  • 18
  • 29
0

You can even do this without an Activity Context, like so:

new Handler(Looper.getMainLooper()).post( () -> 
    Toast.makeText(context, "Toast!", Toast.LENGTH_SHORT).show());
AtomicBoolean
  • 1,070
  • 13
  • 19