创建TCP Cient连接以发送和接收消息

时间:2017-12-13 09:03:07

标签: java android sockets tcp

我目前正忙于开发一个通过TCP与服务器建立连接的应用程序。我目前与服务器有连接,但当我尝试向服务器发送消息时,我的应用程序崩溃时出现android.os.NetworkOnMainThreadException错误。

编辑:通过使用函数TCP.sendMessage()向服务器发送消息,发生此崩溃,其余代码将在doInbackGround内部的asynctask内正确运行,但我调用的函数发送消息变成了活动。

这是我的代码:

package jabo.com.roommapper2.TCP;

import android.os.AsyncTask;
import android.util.Log;

public class TCPThread extends Thread {
    private TcpClient mTcpClient = null;
    private boolean mRun = true;
    String TAG = "TCPThread";

    @Override
    public void run(){
        new ConnectTask().execute("");
        while (mRun) {

        }
    }

    public void cancel(){
        mRun = false;
    }

    public boolean sendMessage(String message){
        Log.d(TAG, "sendMessage: "+message);
        if(mTcpClient != null){
            mTcpClient.sendMessage(message);
            return true;
        }
        else{
            return false;
        }
    }

    private class ConnectTask extends AsyncTask<String, String, TcpClient> {

        @Override
        protected TcpClient doInBackground(String... message) {
            //we create a TCPClient object and
            mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
                @Override
                //here the messageReceived method is implemented
                public void messageReceived(String message) {
                    //this method calls the onProgressUpdate
                    //publishProgress(message);
                    Log.i("Debug","Input message: " + message);
                }
            });
            mTcpClient.run();

            return null;
        }

        protected void onProgressUpdate(String... message){

        }
    }
}

线程从我的控制页面活动开始:

package jabo.com.roommapper2.Screens;

import android.app.Activity;
import android.app.FragmentTransaction;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.util.Set;
import java.util.UUID;

import jabo.com.roommapper2.BT.BTConnectie;
import jabo.com.roommapper2.R;
import jabo.com.roommapper2.TCP.TCPThread;
import jabo.com.roommapper2.TCP.TcpClient;
import jabo.com.roommapper2.extraControls.JoystickView;

public class controlPage extends Activity {

    private static final String TAG = "controlPage";
    private JoystickView joystick;
    private int REQUEST_ENABLE_BT = 1;
    public static BTConnectie BT;
    boolean devicefound = false;
    BluetoothAdapter mBluetoothAdapter;
    static Context context;
    static Toast toast;
    TextView roomname;
    private int RUN = 1;
    private int PAUZE = 0;
    private int state = 0;
    TCPThread TCP;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_control_page);
        TCP = new TCPThread();
        TCP.start();
        roomname = findViewById(R.id.RoomName);
        //toast
        Context context = getApplicationContext();
        this.context =context;
        //BT
        String btdeviceName = "LAPTOP-BOAS";
        //String btdeviceHardwareAddress = "F6:D0:05:15:59:26";
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            //
        }
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        String devices[] = new String[] {};
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
            // There are paired devices. Get the name and address of each paired device.
            int i =0;
            for (BluetoothDevice device : pairedDevices) {
                String deviceName = device.getName();
                String deviceHardwareAddress = device.getAddress(); // MAC address
                if(deviceName.equalsIgnoreCase(btdeviceName) /*&& deviceHardwareAddress.equalsIgnoreCase(btdeviceHardwareAddress)*/){
                    devicefound = true;
                    try {
                        BT = new BTConnectie(device);
                        BT.start();
                        Log.d("Device","Connected");
                    }
                    catch (Exception e){

                    }
                    break;
                }
                else{
                    i++;
                    devicefound = false;
                    Log.d(deviceName,btdeviceName);
                    popup("device not found please connect device first");
                    //devices[i] = deviceName;
                    //Log.d(deviceHardwareAddress,btdeviceHardwareAddress);
                    Log.d("Device","not found");
                }
            }
        }
        if (devicefound == false){
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            registerReceiver(mReceiver, filter);
        }
        //Joystick
        joystick = (JoystickView) findViewById(R.id.joystick);

        joystick.setOnJoystickMoveListener(new JoystickView.OnJoystickMoveListener() {

            @Override
            public void onValueChanged(int angle, int input_power, int direction) {
                int power= input_power;
                byte[] message = new byte[4];
                message[2] = (byte)power;
                message[3]= (byte)'\n';
                switch (direction) {
                    case JoystickView.FRONT:
                        message[1] = 1;
                        break;
                    case JoystickView.FRONT_RIGHT:
                        message[1] = 2;
                        break;
                    case JoystickView.RIGHT:
                        message[1] = 3;
                        break;
                    case JoystickView.RIGHT_BOTTOM:
                        message[1] = 4;
                        break;
                    case JoystickView.BOTTOM:
                        message[1] = 5;
                        break;
                    case JoystickView.BOTTOM_LEFT:
                        message[1] = 6;
                        break;
                    case JoystickView.LEFT:
                        message[1] = 7;
                        break;
                    case JoystickView.LEFT_FRONT:
                        message[1] = 8;
                        break;
                    default:
                        message[1] = 0;
                        break;
                }
                message[0] = (byte)(message.length+16);
                try {
                    if (BTConnectie.mConnectedThread.isAlive()) {
                        BTConnectie.mConnectedThread.write(message);
                    } else {
                        popup("cant send to device");
                    }
                }
                catch (Exception e){
                    popup("cant send to device");
                }
            }
        }, JoystickView.DEFAULT_LOOP_INTERVAL);
    }

    public void start(View v){
        if(state == RUN) {
            if (!roomname.getText().toString().equalsIgnoreCase("")) {
                state = PAUZE;
                popup("started");
                TCP.sendMessage("Start<LOG>");
            }
            else{
                popup("Please give a room name");
            }
        }
        else{
            popup("stopped");
            state = RUN;
            TCP.sendMessage("Stop<LOG>");
        }
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        Log.d(TAG, "onDestroy: destroyed");
        TCP.cancel();
        //BT.cancel();

    }

    @Override
    protected void onPause(){
        super.onPause();
        Log.d(TAG, "onPause: paused");
    }

    @Override
    protected void onStop(){
        super.onStop();
        Log.d(TAG, "onStop: stopped");
    }


    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Discovery has found a device. Get the BluetoothDevice
                // object and its info from the Intent.
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String deviceName = device.getName();
                String deviceHardwareAddress = device.getAddress(); // MAC address
            }
        }
    };

    public static void popup(String message){
        int duration = Toast.LENGTH_SHORT;
        if(toast != null) {
            toast.cancel();
            toast = Toast.makeText(context,message,duration);
            toast.show();
        }
        else {
            toast = Toast.makeText(context,message,duration);
            toast.show();
        }
    }
}

我的问题是如何正确调用TCP.sendMessage() 此功能在启动功能中调用,按下按钮时将调用该功能。

线程调用TcpClient类,如下所示:

package jabo.com.roommapper2.TCP;

import android.os.Message;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * Description
 *
 * @author Catalin Prata
 *         Date: 2/12/13
 */
public class TcpClient {

    final String TAG = "TcpClient";

    public static final String SERVER_IP = "192.168.101.11"; //your computer IP address
    public static final int SERVER_PORT = 11000;
    // message to send to the server
    private String mServerMessage;
    // sends message received notifications
    private OnMessageReceived mMessageListener = null;
    // while this is true, the server will continue running
    private boolean mRun = false;
    // used to send messages
    private PrintWriter mBufferOut;
    // used to read messages from the server
    private BufferedReader mBufferIn;

    /**
     * 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 (mBufferOut != null && !mBufferOut.checkError()) {
            mBufferOut.println(message);
            mBufferOut.flush();
        }
    }

    /**
     * Close the connection and release the members
     */
    public void stopClient() {
        Log.i("Debug", "stopClient");

        // send mesage that we are closing the connection
        //sendMessage(Constants.CLOSED_CONNECTION + "Kazy");

        mRun = false;

        if (mBufferOut != null) {
            mBufferOut.flush();
            mBufferOut.close();
        }

        mMessageListener = null;
        mBufferIn = null;
        mBufferOut = null;
        mServerMessage = null;
    }

    public void run() {

        mRun = true;

        try {
            //here you must put your computer's IP address.
            Log.e("TCP Client", "C: Connecting...");

            //create a socket to make the connection with the server
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), 10000);
            //socket.connect(,30*1000);

            try {
                Log.i("Debug", "inside try catch");
                //sends the message to the server
                mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                //receives the message which the server sends back
                mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                // send login name
                //sendMessage(Constants.LOGIN_NAME + PreferencesManager.getInstance().getUserName());
                //sendMessage("Hi");
                //in this while the client listens for the messages sent by the server
                while (mRun) {
                    mServerMessage = mBufferIn.readLine();
                    if (mServerMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(mServerMessage);
                    }

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

            } 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);
    }
}

我在Android设备上使用Android 4.4.2进行了连接,现在我忙于安卓7,现在它停止工作了,有解释吗?

如果我的代码中有一些荷兰语单词,那是因为我住在荷兰,所以也很抱歉我的英语不好。

提前致谢

编辑:

我已经解决了我的问题,我用以下方法做到了:

new Thread(new Runnable() {
                    @Override
                    public void run() {
                        TCP.sendMessage(name+"<NAME>");
                        TCP.sendMessage("<RMAP>");
                    }
                }).start();

感谢所有帮助过的人

0 个答案:

没有答案