I am trying to connect my App to the bluetooth device and after that i am doing the functionality Read and Write. I am able to do connectivity and Write command to device. But i am not able to do Read functionality.
The "Read" functionality is like, as soon as device socket will get connect to the App, it should send the device information continuously. But i my case, read() method is calling but every time i am getting the length on InputStream in 0.
Below is the code what i am writing. Please check it where i am going wrong and please help me.
public class ConnectionThread implements Runnable {
private static final String CLASSTAG = ConnectionThread.class.getSimpleName();
public static BluetoothSocket mSocket;
private InputStream inStream;
private OutputStream outStream;
private boolean canceled = false;
private Context mContext;
public ConnectionThread(Context context, BluetoothDevice device) {
this.mContext = context;
try {
mSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(Constants.mUUID));
} catch (IOException e) {
Log.e(CLASSTAG, "createRfcommSocketToServiceRecord", e);
}
}
#SuppressLint("NewApi")
#Override
public void run() {
// Cancel discovery because it will slow down the connection
if(BluetoothAdapter.getDefaultAdapter().isDiscovering()) {
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
}
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mSocket.connect();
} catch (IOException e) {
Log.e(CLASSTAG, "connect failed", e);
// Unable to connect; close the socket and get out
disconnect();
return;
}
// Get the input and output streams, using temp objects because
// member streams are final
try {
inStream = mSocket.getInputStream();
outStream = mSocket.getOutputStream();
} catch (IOException e) {
Log.e(CLASSTAG, "IO streams init failed", e);
disconnect();
return;
}
while (!canceled) {
read();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Log.e(CLASSTAG, "sleep failed", e);
}
}
}
#SuppressLint("NewApi")
public void applyCommand(String configCommand) throws IOException {
byte[] bytes = null;
bytes = new BigInteger(configCommand,16).toByteArray();
if (mSocket.isConnected()) {
//write(bytes);
outStream.write(bytes);
Log.d(CLASSTAG, "Command apply: " + bytes + " (" + configCommand + ")");
}
Toast.makeText(mContext, mContext.getString(R.string.cmd_updated), Toast.LENGTH_LONG).show();
}
private void read() {
byte[] buffer = new byte[128];
// Keep listening to the InputStream while connected
try {
// Read from the InputStream
if (inStream.available() > 0) {
int bytes = inStream.read(buffer);
if (bytes > 0) {
Log.d(CLASSTAG, "Response: " + new String(buffer, 0, bytes));
}
}
// Send the obtained bytes to the UI Activity
// mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(CLASSTAG, "reading from input stream failed", e);
disconnect();
}
}
public void disconnect() {
try {
if (outStream != null) {
outStream.close();
}
if (inStream != null) {
inStream.close();
}
mSocket.close();
canceled = true;
} catch (IOException e) {
Log.e(CLASSTAG, "close socket", e);
}
}
}
Related
I want to create two apps in android java, to connect through bluetooth and send and receive data. I already implement both apps. but the problem is when i want to connect more than one client to the server app and send data from all clients to the server. but server only can get data from first client. before i heard one server can connect to five client at the same time.
is it right?
private class Server extends Thread {
private BluetoothServerSocket serverSocket;
public Server() {
try {
serverSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(APP_NAME, uuid);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
BluetoothSocket bluetoothSocket = null;
while (bluetoothSocket == null) {
try {
bluetoothSocket = serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
if (bluetoothSocket != null) {
sendReceive = new SendReceive(bluetoothSocket);
sendReceive.start();
break;
}
}
}
}
private class SendReceive extends Thread {
private BluetoothSocket socket;
private InputStream inputStream;
private OutputStream outputStream;
public SendReceive(BluetoothSocket socket1) {
socket = socket1;
InputStream tempIn = null;
OutputStream tempOut = null;
try {
tempIn = socket.getInputStream();
tempOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
inputStream = tempIn;
outputStream = tempOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while (true){
try {
bytes = inputStream.read(buffer);
Log.i(TAG, "server receive: " + new String(buffer, 0 , buffer.length).trim());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write(byte[] bytes){
try {
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class Client extends Thread {
BluetoothDevice device;
BluetoothSocket socket;
public Client(BluetoothDevice device1) {
device = device1;
try {
socket = device.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try {
socket.connect();
sendReceive = new SendReceive(socket);
sendReceive.start();
} catch (IOException e) {
e.printStackTrace();
Log.i("blt", "run Client " + e.getMessage());
}
}
}
private class SendReceive extends Thread {
private BluetoothSocket socket;
private InputStream inputStream;
private OutputStream outputStream;
public SendReceive(BluetoothSocket socket1) {
socket = socket1;
InputStream tempIn = null;
OutputStream tempOut = null;
try {
tempIn = socket.getInputStream();
tempOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
Log.i("blt", "SendReceive " + e.getMessage());
}
inputStream = tempIn;
outputStream = tempOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
bytes = inputStream.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void write(byte[] bytes) {
try {
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
what should i change in my code to be able to connect more than one client to the server and receive data from all clients?
My Application contains 3 Activities -
MainActivity.java
Write.java
BluetoothConnectionService.java
BluetoothConnectionService.java
public class BluetoothConnectionService {
private static final String TAG = "BluetoothConnectionServ";
private static final String appName = "MYAPP";
private static final UUID MY_UUID_INSECURE =
UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
private final BluetoothAdapter mBluetoothAdapter;
Context mContext;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private BluetoothDevice mmDevice;
private UUID deviceUUID;
ProgressDialog mProgressDialog;
private ConnectedThread mConnectedThread;
public BluetoothConnectionService(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//start();
}
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread(){
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try{
tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(appName, MY_UUID_INSECURE);
Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE);
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
mmServerSocket = tmp;
}
public void run(){
Log.d(TAG, "run: AcceptThread Running.");
BluetoothSocket socket = null;
try{
// This is a blocking call and will only return on a
// successful connection or an exception
Log.d(TAG, "run: RFCOM server socket start.....");
socket = mmServerSocket.accept();
Log.d(TAG, "run: RFCOM server socket accepted connection.");
}catch (IOException e){
Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
}
if(socket != null){
connected(socket,mmDevice);
}
Log.i(TAG, "END mAcceptThread ");
}
public void cancel() {
Log.d(TAG, "cancel: Canceling AcceptThread.");
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() );
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
public ConnectThread(BluetoothDevice device, UUID uuid) {
Log.d(TAG, "ConnectThread: started.");
mmDevice = device;
deviceUUID = uuid;
}
public void run(){
BluetoothSocket tmp = null;
Log.i(TAG, "RUN mConnectThread ");
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: "
+MY_UUID_INSECURE );
tmp = mmDevice.createRfcommSocketToServiceRecord(deviceUUID);
} catch (IOException e) {
Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage());
}
mmSocket = tmp;
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
Log.d(TAG, "run: ConnectThread connected.");
//mProgressDialog.cancel();
//Toast.makeText(mContext,"Connected", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
Log.d(TAG, "run: Closed Socket.");
} catch (IOException e1) {
Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage());
}
Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE );
}
connected(mmSocket,mmDevice);
}
public void cancel() {
try {
Log.d(TAG, "cancel: Closing Client Socket.");
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage());
}
}
}
private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
Log.d(TAG, "connected: Starting.");
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
//start new activity
Intent intent = new Intent(mContext, Write.class);
mContext.startActivity(intent);
}
/**
Finally the ConnectedThread which is responsible for maintaining the BTConnection, Sending the data, and
receiving incoming data through input/output streams respectively.
**/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "ConnectedThread: Starting.");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
//dismiss the progress dialog when connection is established
try{
mProgressDialog.dismiss();
}catch (NullPointerException e){
e.printStackTrace();
}
try {
tmpIn = mmSocket.getInputStream();
tmpOut = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run(){
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
// Read from the InputStream
try {
bytes = mmInStream.read(buffer);
String incomingMessage = new String(buffer, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
Intent incomingMessageIntent = new Intent("incomingMessage");
incomingMessageIntent.putExtra("theMessage", incomingMessage);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(incomingMessageIntent);
Log.d(TAG, "broadcast sent");
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
//Call this from the main activity to send data to the remote device
/*public void write(byte[] bytes) {
String text = new String(bytes, Charset.defaultCharset());
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
}
}*/
public void write(String input) {
byte[] msgBuffer = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(msgBuffer); //write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(mContext, "Connection Failure", Toast.LENGTH_LONG).show();
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
public void start() {
Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread();
mInsecureAcceptThread.start();
}
}
public void startClient(BluetoothDevice device,UUID uuid){
Log.d(TAG, "startClient: Started.");
//init progress dialog
mProgressDialog = ProgressDialog.show(mContext,"Connecting Bluetooth"
,"Please Wait...",true);
mConnectThread = new ConnectThread(device, uuid);
mConnectThread.start();
}
/**
* Write to the ConnectedThread in an unsynchronized manner
*
*/
public void write() {
// Create temporary object
//ConnectedThread r;
// Synchronize a copy of the ConnectedThread
Log.d(TAG, "write: Write Called.");
//perform the write
mConnectedThread.write("1");
}
}
PROBLEM:-
From the MainActivity, I created a BluetoothConnectionService object
BluetoothConnectionService mBluetoothConnection = new BluetoothConnectionService(MainActivity.this);
Then, I called startClient(device,uuid) method on mBluetoothConnection object
mBluetoothConnection.startClient(device,uuid);
Now, after successful connection is made, I can send out data to other devices by calling write() from the MainActivity
mBluetoothConnection.write();
But I don't want to send out data from MainActivity instead I want to use Write activity to send data out. How can I do that?
The Code you are using is provided by google Bluetooth chat application and they write using this:
In your Activity
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (bluetoothConnectionService.getState() != BluetoothConnectionService.STATE_CONNECTED) {
Toast.makeText(MainActivity.this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothConnectionService to write
byte[] send = message.getBytes();
bluetoothConnectionService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
}
}
In the service add these two methods
/**
* Write to the ConnectedThread in an unsynchronized manner
*
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
/**
* Write to the connected OutStream.
*
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
I am working with the Bluetooth chat example and I am trying to send "dummy" data in specific intervals from a thread that's active when the Bluetooth device is connected. Is it a good idea to start/stop another service to call a method in the original service every so often? How would I implement this?
private class ConnectedThread extends Thread {
static private final String TAG = "PhoneInfoConnectedThread";
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
Log.d(TAG, "In and out streams created");
} catch (IOException e) {
Log.e(TAG, "temp sockets not created " + e.getMessage());
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
// this is where we will spend out time when connected to the accessory.
public void run() {
// Keep listening to the InputStream while connected
while (true) {
// do whatever
}
}
// Write to the connected OutStream.
public void write(byte[] buffer) {
if (mmOutStream == null) {
Log.e(TAG, "ConnectedThread.write: no OutStream");
return;
}
try {
Log.d(TAG, "ConnectedThread.write: writing " + buffer.length
+ " bytes");
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
// mHandler.obtainMessage(PhoneInfoActivity.MESSAGE_WRITE, -1,
// -1, buffer).sendToTarget();
Log.d(TAG, "ConnectedThread.write: sent to calling activity");
} catch (IOException e) {
Log.e(TAG, "Exception during write" + e.getMessage());
}
}
public void cancel() {
try {
Log.d(TAG, "ConnectedThread.cancel: closing socket");
if (mmSocket != null)
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "ConnectedThread.cancel: socket.close() failed"
+ e.getMessage());
}
}
}
May this example help you.
MyTimerTask myTask = new MyTimerTask();
Timer myTimer = new Timer();
myTimer.schedule(myTask, 2000, 1000);
class MyTimerTask extends TimerTask {
public void run() {
Log.v("TAG","Message");
}
}
for more information see this
I'm using an AsyncTask to establish a TCP Connection and sending/receiving data through it.
My current Code looks like this at the moment:
public class NetworkTask extends AsyncTask<Void, byte[], Boolean> {
Socket nsocket; //Network Socket
InputStream nis; //Network Input Stream
OutputStream nos; //Network Output Stream
boolean bSocketStarted = false;
byte[] buffer = new byte[4096];
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected Boolean doInBackground(Void... params) { //This runs on a different thread
boolean result = false;
try {
// Connect to address
Log.i(TAG, "doInBackground: Creating socket");
SocketAddress sockaddr = new InetSocketAddress("google.de", 80);
nsocket = new Socket();
nsocket.connect(sockaddr, 5000); //10 second connection timeout
if (nsocket.isConnected()) {
bSocketStarted = true;
nis = nsocket.getInputStream();
nos = nsocket.getOutputStream();
Log.i("AsyncTask", "doInBackground: Socket created, streams assigned");
Log.i("AsyncTask", "doInBackground: Waiting for inital data...");
int read = nis.read(buffer, 0, 4096); //This is blocking
while(bSocketStarted) {
if (read > 0){
byte[] tempdata = new byte[read];
System.arraycopy(buffer, 0, tempdata, 0, read);
publishProgress(tempdata);
Log.i(TAG, "doInBackground: Got some data");
}
}
}
} catch (IOException e) {
e.printStackTrace();
Log.i(TAG, "doInBackground: IOException");
result = true;
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "doInBackground: Exception");
result = true;
} finally {
try {
nis.close();
nos.close();
nsocket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.i(TAG, "doInBackground: Finished");
}
return result;
}
public boolean SendDataToNetwork(final byte[] cmd) { //You run this from the main thread.
// Wait until socket is open and ready to use
waitForSocketToConnect();
if (nsocket.isConnected()) {
Log.i(TAG, "SendDataToNetwork: Writing received message to socket");
new Thread(new Runnable() {
public void run() {
try {
nos.write(cmd);
}
catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "SendDataToNetwork: Message send failed. Caught an exception");
}
}
}
).start();
return true;
}
else
Log.i(TAG, "SendDataToNetwork: Cannot send message. Socket is closed");
return false;
}
public boolean waitForSocketToConnect() {
// immediately return if socket is already open
if (bSocketStarted)
return true;
// Wait until socket is open and ready to use
int count = 0;
while (!bSocketStarted && count < 10000) {
try {
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
count += 500;
}
return bSocketStarted;
}
#Override
protected void onProgressUpdate(byte[]... values) {
try {
if (values.length > 0) {
Log.i(TAG, "onProgressUpdate: " + values[0].length + " bytes received.");
String str = new String(buffer, "UTF8");
Log.i(TAG,str);
tv.setText(str);
tv.setMovementMethod(new ScrollingMovementMethod());
}
} catch (Exception e) {
e.printStackTrace();
}
finally {}
}
#Override
protected void onCancelled() {
Log.i(TAG, "Cancelled.");
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
Log.i(TAG, "onPostExecute: Completed with an Error.");
} else {
Log.i(TAG, "onPostExecute: Completed.");
}
}
}
I can instantiate the Task and call SendDataToNetwork from my activity. However, all the text I pass to SendDataToNetwork, for example, 'GET / HTTP/1.1' is continously sent to the server.
How can I modify my Code to maintain the connection in doInBackground and do nothing until I call SendDataToNetwork and after sending bytes to the server just wait until new data is ready to be sent? Basically I want to run the AsyncTask until I explicitly cancel (= close the connection) it.
nsocket.connect(sockaddr, 5000); //10 second connection timeout
if (nsocket.isConnected()) {
The test is pointless. If the socket wasn't connected, connect() would have thrown an exception.
Your read loop is also fundamentally flawed, in that it doesn't keep reading. There are standard solutions as to how to read a stream, e.g.:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Your waitForSocketToConnect() method doesn't really do anything useful either.
You need to rethink all this.
I write some client-server communication.
My server:
public class Server {
public synchronized static void sendPacket(Packet packet,
ObjectOutputStream server) {
try {
server.writeObject(packet);
server.flush();
} catch (IOException e) {
Log.d(TAG, "Error while sending a packet. Output stream is unaviable.");
}
}
public synchronized static Packet readPacket(ObjectInputStream sourceStream) {
Packet recivedPacket = null;
try {
recivedPacket = (Packet) sourceStream.readObject();
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return recivedPacket;
}
/** Register user on the server */
private User registerUser(Socket socket) {
ClientUserLoginPacket newUserPacket = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
Log.i(TAG, "Opening output stream...");
oos = new ObjectOutputStream(socket.getOutputStream());
if (oos != null)
Log.d(TAG, "Output stream opened");
Log.i(TAG, "Opening input stream...");
ois = new ObjectInputStream(socket.getInputStream());
if (ois != null)
Log.d(TAG, "Input stream opened");
} catch (StreamCorruptedException e1) {
Log.e(TAG, "Error while opening stream");
} catch (IOException e1) {
e1.printStackTrace();
}
// First packet MUST be register request
try {
Log.d(TAG, "Waiting for login packet from client...");
newUserPacket = (ClientUserLoginPacket) readPacket(ois);
Log.d(TAG, "Login packet from recived...");
} catch (Exception e) {
Log.e(TAG, "Can't recive login packet.");
}
User newUserInstance = null;
// TODO check if exists. or to map in the future
if (newUserPacket != null) {
newUserInstance = new User(socket, ois, oos, newUserPacket.nick);
users.add(newUserInstance);
Log.d(TAG, "User " + newUserPacket.nick + " registered.");
Server.sendPacket(new ServerLoginAcceptedPacket(), oos);
Log.d(TAG, "User accept confirmation sent.");
}
return newUserInstance;
}
#Override
public void run() {
Log.i(TAG, "Starting server...");
ServerSocket server;
try {
server = new ServerSocket(PORT);
Log.i(TAG, "Server started.");
server.setSoTimeout(0);
while (true) {
Log.i(TAG, "Waiting for players...");
final Socket socket = server.accept();
Log.i(TAG, "New player connected.");
new Thread(new Runnable() {
#Override
public void run() {
Log.i(TAG, "Try to register new player.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
User user = registerUser(socket);
while (true) {
Log.i(TAG, "Waiting for packets from " + user.nick+"...");
Packet packet = readPacket(user.ois);
Log.i(TAG, "Packet from " + user.nick + " recived.");
if (packet instanceof ...) {
...
}
}
}
}).start();
}
} catch (IOException e) {
Log.i(TAG, "Port is busy.");
}
}
private class User {
public Socket connection;
public ObjectInputStream ois;
public ObjectOutputStream oos;
public String nick;
public boolean inGame;
public User(Socket socket, ObjectInputStream ois,
ObjectOutputStream oos, String nick) {
this.connection = socket;
this.ois = ois;
this.oos = oos;
this.nick = nick;
}
// ...
}
My client:
public class Client {
callbackHandler = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
Log.e(TAG, "Waiting for incomeing packets...");
Packet packet = (Packet) Server.readPacket(serverInput);
Log.e(TAG, "Packet recived.");
if (packet instanceof ServerLoginAcceptedPacket) {
Log.e(TAG, "Recived packet is "
+ packet.getClass().toString());
Intent intent = new Intent(MyActivity.this,
MainMenuActivity.class);
MyActivity.this.startActivity(intent);
}
}
}
});
public void connectToServer() {
SocketAddress sockaddr = new InetSocketAddress(mEditTextIp.getText()
.toString(), Server.PORT);
server = new Socket();
try {
server.setSoTimeout(1000);
Log.d(TAG, "Connecting to server.");
server.connect(sockaddr, Server.PORT);
Log.d(TAG, "Connected to server.");
} catch (IOException e) {
Log.e(TAG, "Can't connect to server.");
server = null;
}
if (server != null)
try {
server.setSoTimeout(0);
Log.d(TAG, "Opening output stream...");
serverOutput = new ObjectOutputStream(server.getOutputStream());
if (serverOutput != null)
Log.d(TAG, "Output stream opened");
else
Log.e(TAG, "Error while opening output stream");
} catch (IOException e) {
Log.e(TAG, "Server socket probably closed");
}
}
public void requestLogin() {
new Thread(new Runnable() {
#Override
public void run() {
Log.e(TAG, "Sending login packet...");
Server.sendPacket(new ClientUserLoginPacket(mEditTextLogin
.getText().toString(), ""), serverOutput); // TODO send
// pass and
// email
Log.e(TAG, "Login packet send");
}
}).start();
}
public void authenticate(View v) {
if (server == null)
connectToServer();
if (server != null) {
requestLogin();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
serverInput = new ObjectInputStream(server.getInputStream());
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (serverInput != null) {
Log.e(TAG, "Start reciving callbacks...");
callbackHandler.start();
} else {
Log.d(TAG, "Can't open input stream to server.");
}
}
}
public void runServer(View v) {
new Thread(new Server()).start();
Toast.makeText(this, "Server running...", 1000).show();
}
}
Where runServer() and authenticate() functions are triggered with button.
Problem is that after server recive ClientLoginPacket, all subsequent sentPacket functions hangs on oos.writeObject().
I think the order of reading/writing from/to streams may be wrong.
What should be correct order of opening streams and writing objects to them?
Do I have to write something to ObjectOutputStream before opening ObjectInputStream?
After few hours I found that keywords synchronized before my methods readPacket() and sendPacket() were problem. ;)