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