0

Android アプリケーションを継承し、最新の API に更新しています。NetworkOnMainThreadExceptionソケットを作成するときに取得しています。を使用するという多くのソリューションを読みましたAsyncTask。ただしAsyncTask、実行時間の短いタスクにのみ使用してください。これは、実行中のアプリケーションの存続期間中続く標準の TCP 接続です。双方向です。

スレッドを使用してクラスを更新し、例外が発生せず、ソケット経由でデータを送信できるようにするにはどうすればよいですか?

public class TcpConnection
{
    enum State
{
    Closed,
    Closing,
    Open
};

State _state;    
Socket _socket;
//data stream from the head-unit
DataInputStream _inputStream;
//data stream to the head-unit
DataOutputStream _outputStream;

Receiver _receiver;
Thread _thread;

OnTcpDataReceivedListener _onTcpDataReceived;

public TcpConnection()
{                 
     _state = State.Closed;
}

// Listen to this to be informed of what data has been received from a TCP / IP socket.
public void setOnTcpDataReceivedListener(OnTcpDataReceivedListener listener)   
{
    _onTcpDataReceived = listener;
}

// Used to inform the listener that data has been received from a TCP / IP socket.
public interface OnTcpDataReceivedListener
{
    public void onTcpDataReceived(byte[] buffer, int length);
}

// Try connecting to a given TCP / IP connection.
// Notes:
// Blocks until a connection is created.
// if connected
public synchronized void connect(String ipAddress, int port) 
throws IOException
{
    if (_state != State.Closed)
        return;

    try
    {
        _state = State.Open;

        _socket = new Socket(ipAddress, port);
        _inputStream = new DataInputStream(_socket.getInputStream());
        _outputStream = new DataOutputStream(_socket.getOutputStream());            
    }
    catch(IOException ex)
    {            
        //TODO: do better error handling
        ex.printStackTrace();

        if (_socket != null) {
            _socket.close();
            _socket = null;             
        }

        if (_inputStream != null) {
            _inputStream.close();
            _inputStream = null;
        }

        if (_outputStream != null) {
            _outputStream.close();
            _outputStream = null;
        }

        throw ex;
    }

    _receiver = new Receiver();

    _thread = new Thread(_receiver);
    _thread.setName("TcpConnection.Receiver");
    _thread.start();
}

public void write(byte[] buffer)
{
    if (_state != State.Open)
        return;

    try
    {
        _outputStream.write(buffer);
    }
    catch(IOException ex)
    {            
        //TODO: do better error handling
        ex.printStackTrace();            
    } 
}

public synchronized void close()
{
    _state = State.Closing;

    if (_socket != null && !_socket.isClosed())
    {
        try
        {
            _socket.close();
        }
        catch(IOException ex)
        {
            //TODO: do better error handling
            ex.printStackTrace();
        }
    }         
}

private class Receiver implements Runnable
{                                  
    @Override
    public void run() 
    {                        
        try 
        {
            byte[] buffer = new byte[512];
            int read = 0;

            while(_state == State.Open)
            {                    
                read = _inputStream.read(buffer);

                if (read > 0)
                {
                    if (_onTcpDataReceived != null)
                    {
                        _onTcpDataReceived.onTcpDataReceived(buffer, read);
                    }
                }
            }
        }
        catch (SocketException ex)
        {
            if (    !(_state != State.Open 
                    && ex.getMessage() != null 
                    && ex.getMessage().equalsIgnoreCase("socket closed")))
            {
                ex.printStackTrace();
            }
        }
        catch (IOException ex) 
        {
            //TODO: need error handling
            ex.printStackTrace();
        }            
        finally 
        {
            if (_socket != null && !_socket.isClosed())
            {
                try
                {
                    _socket.close();
                }
                catch (IOException ex) 
                {
                    //TODO: need error handling
                    ex.printStackTrace();
                }                    
            }
        }

        _state = State.Closed;
     }
}   

}

4

1 に答える 1

0

いくつかの選択肢があります。

  1. 別のスレッドでTcpConnectionすべての呼び出しをラップするために使用する実際の Android クラスを更新します。それを作成して使用できます。TcpConnectionExecutor
  2. すべての送受信を処理するExecutorインスタンスを追加します。TcpConnectionあなたの問題はconnect関数にあると思います。そのコードを別の Runnable にラップして、スレッドで起動してみてください。
于 2013-05-13T20:35:36.343 に答える