0

The idea is when the TCP server receives a String message, if it is equal to "::turnOnBluetoothOn::". Will simply turn on the bluetooth on the device. By using the runCommand Method of the MessageHandler class. The problem is that I am getting the error Can't create handler inside thread that has not called Looper.prepare()

Here is my code:

import android.os.Looper;
import android.util.Log;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;

public class TCPClient
{
    private String serverMessage;
    // <<<<<<< .mine
    public static final String SERVERIP = "xx.xxx.xx.xx"; // your computer IP

    public static final int SERVERPORT = 4444;
    private OnMessageReceived mMessageListener = null;
    private boolean mRun = false;

    PrintWriter out;
    BufferedReader in;

    // Test for Thread
    private volatile Looper mMyLooper;

    /**
     * Constructor of the class. OnMessagedReceived listens for the messages
     * received from server
     */
    public TCPClient(OnMessageReceived listener)
    {
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     * 
     * @param message
     *            text entered by client
     */
    public void sendMessage(String message)
    {
        if (out != null && !out.checkError())
        {
            out.println(message);
            out.flush();
        }
    }

    public void stopClient()
    {
        mRun = false;
    }

    public void run()
    {
        mRun = true;
        try
        {
            // here you must put your computer's IP address.
            InetAddress serverAddr = InetAddress.getByName(SERVERIP);

            Log.e("TCP Client", "C: Connecting...");

            // create a socket to make the connection with the server
            Socket socket = new Socket(serverAddr, SERVERPORT);

            try
            {
                // send the message to the server
                out = new PrintWriter(new BufferedWriter(
                        new OutputStreamWriter(socket.getOutputStream())), true);

                Log.e("TCP Client", "C: Sent.");

                Log.e("TCP Client", "C: Done.");

                // receive the message which the server sends back
                in = new BufferedReader(new InputStreamReader(
                        socket.getInputStream()));

                // in this while the client listens for the messages sent by the
                // server
                while (mRun)
                {
                    serverMessage = in.readLine();

                    if (serverMessage != null && mMessageListener != null)
                    {
                        // call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(serverMessage);
                        System.out.println(serverMessage);

                        MessageHandler handler = new MessageHandler(serverMessage);
                        handler.runCommand();

                    }    

                    serverMessage = null;
                }

                Log.e("RESPONSE FROM SERVER", "S: Received Message: '"
                        + serverMessage + "'");

            } catch (Exception e)
            {

                Log.e("TCP", "S: Error", e);

            }
            finally
            {
                // the socket must be closed. It is not possible to reconnect to
                // this socket
                // after it is closed, which means a new socket instance has to
                // be created.
                socket.close();
            }

        } catch (Exception e)
        {
            Log.e("TCP", "C: Error", e);
        }
    }

    // Declare the interface. The method messageReceived(String message) will
    // must be implemented in the MyActivity
    // class at on asynckTask doInBackground
    public interface OnMessageReceived
    {
        public void messageReceived(String message);
    }
}

//AND THIS IS THE HANDLER CLASS

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;

public class MessageHandler extends Activity
{
    private static final int REQUEST_ENABLE_BT = 0;
    private static final int REQUEST_DISCOVERABLE_BT = 0;
    final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    private String Instruction;

    MessageHandler(String Command)
    {
        Instruction = Command;
    }

    public void runCommand()
    {
        if (Instruction.equals("::turnBluetoothOn::"))
        {
            if (!mBluetoothAdapter.isEnabled())
            {
                Intent enableBtIntent = new               Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
            return;
        }
    }
}

Update: Here is the LogCat:

03-01 18:16:09.486: I/System.out(4752): ::turnBluetoothOn::
03-01 18:16:09.526: D/AndroidRuntime(4752): Shutting down VM
03-01 18:16:09.526: W/dalvikvm(4752): threadid=1: thread exiting with uncaught exception (group=0x4193a700)

03-01 18:16:09.546: E/AndroidRuntime(4752): FATAL EXCEPTION: main
03-01 18:16:09.546: E/AndroidRuntime(4752): java.lang.NullPointerException
03-01 18:16:09.546: E/AndroidRuntime(4752):     at com.example.myactivity.MessageHandler.runCommand(MessageHandler.java:22)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at com.example.myactivity.TCPClient$1.run(TCPClient.java:108)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at android.os.Handler.handleCallback(Handler.java:730)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at android.os.Handler.dispatchMessage(Handler.java:92)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at android.os.Looper.loop(Looper.java:137)
03-01 18:16:09.546: E/AndroidRuntime(4752):     at android.app.ActivityThread.main(ActivityThread.java:5103)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at java.lang.reflect.Method.invokeNative(Native Method)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at java.lang.reflect.Method.invoke(Method.java:525)
03-01 18:16:09.546: E/AndroidRuntime(4752):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)

03-01 18:16:09.546: E/AndroidRuntime(4752):     at dalvik.system.NativeStart.main(Native Method)
Menma
  • 799
  • 1
  • 9
  • 35

2 Answers2

1

try this:

if (serverMessage != null && mMessageListener != null)
{
  // call the method messageReceived from MyActivity class
  mMessageListener.messageReceived(serverMessage);

  new Handler(Looper.getMainLooper()).post(new Runnable() {             
    @Override
    public void run() { 
      MessageHandler handler = new MessageHandler(serverMessage);
      handler.runCommand();
    }
  });
}    
Rick Royd Aban
  • 904
  • 6
  • 33
0

According to the error information,you create handler inside a non-ui thread, you have declared mMyLooper,why not use it? so my advice is that add this code: mMyLooper = Looper.getMainLooper(); Looper.prepare(); before while (mRun).

storkzhang
  • 31
  • 4
  • I updated the code, by adding the error I get in te LogCat. I tried you solution but it did not work. – Alberto Di Martino Mar 02 '14 at 00:41
  • From your error information in LogCat,will mBluetoothAdapter be null? the error shows that ,your code at line 22 has called a fatal exception,try to debug and toggle a breakpoint at line 22. – storkzhang Mar 03 '14 at 08:00