So I am working on an app that is involving sockets. Multiple strings is sent through the socket, the receiving end receives it, and updates the RecyclerView correspondingly. It's working fine, that is until the app crashes / restarts. I do not know what happens, but there's this app called XRecorder on Play Store and everytime I use the screenshot function- my app restarts. Now when I send a message through the socket, it receives the message but it doesn't update the RecyclerView? The Toast appears that's why I know it is received. And it updates as well when I call removeItem()
Here's my code :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
serverAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private class ServerAsync extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
try {
serverSocket = new ServerSocket(serverPort);
while (true) {
Socket client = serverSocket.accept();
isConnected = client.isConnected();
if (isConnected) {
try {
handler.post(new Runnable() {
#Override
public void run() {
updateStatusUI();
}
});
Entry entry = new Entry();
String inputLine;
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
while ((inputLine = in.readLine()) != null) {
StringBuilder sb = new StringBuilder();
String message = inputLine;
sb.append(message);
entry.add(sb.toString());
}
//READ NEW ENTRIES
handler.post(new Runnable() {
#Override
public void run() {
splitOrder(entry);
saveArrayList();
}
});
in.close();
handler.post(new Runnable() {
#Override
public void run() {
entryAdapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), "In has closed :" + client.getRemoteSocketAddress(), Toast.LENGTH_SHORT).show();
updateStatusUI();
}
});
} catch (Exception e) {
Log.e("TEST", e.getMessage(), e);
}
} else {
Toast.makeText(getApplicationContext(), "Client :" + client.getRemoteSocketAddress()+" has DISCONNECTED", Toast.LENGTH_SHORT).show();
handler.post(new Runnable() {
#Override
public void run() {
updateStatusUI();
}
});
}
}
} catch (Exception e) {
Log.e("UHE", e.getMessage(), e);
}
return null;
}
}
public void removeItem(int position) {
entryAdapter.notifyDataSetChanged();
}
I've tried resetting the adapter for the RecyclerView, but it just wouldn't work. I also noticed that everytime I the app crashes and restart, I am getting the java.net.BindException: bind failed: EADDRINUSE (Address already in use)
Pointing to the creation of my serverSocket (serverSocket = new ServerSocket(serverPort)
Could this be the reason why the RecyclerView won't update? The ArrayList updates just fine with the incoming messages, but not the view.
Related
I am creating a small game over wifi-direct through sockets on Android. On the client receiving thread I am listening for Messages from the other device:
class ReceivingThread implements Runnable {
#Override
public void run() {
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
while (!Thread.currentThread().isInterrupted()) {
final String messageStr = input.readLine();
if (messageStr != null) {
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, messageStr, Toast.LENGTH_LONG).show();
activity.handleMessage(messageStr);
}
});
} else {
break;
}
}
input.close();
} catch (IOException e) {
}
}
}
And the toast shows the message just fine, but the app crashes on activity.handleMessage(). This is what the method does (cut it down just to one case, just for the point of the method):
public void handleMessage(String msg){
switch(msg){
case "1":
Button temp = (Button) findViewById(btn1);
if(isOwner) {
temp.setText("O");
} else {
temp.setText("X");
}
temp.setEnabled(false);
break;
case "You Lose":
TextView textBox = (TextView) findViewById(R.id.textBox);
textBox.setText("You Lose!");
}
}
And the message I get is:
java Looper.prepare() wasn't called on this thread.
Instead of activity.handleMessage(messageStr); you need to send it as a message to the handler, so handleMessage will execute in the loop.
Bundle data = new Bundle();
data.putString("MESSAGE_KEY", messageStr);
Message msg = new Message();
msg.setData(data);
activity.sendMessage(msg);
So you will receive in handleMessage of the Handler the Message, to extract the String you do message.getData().getString("MESSAGE_KEY");
Create UI thread inside handler and try to perform the UI operation.
new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message message) {
// This is where you do your work in the UI thread.
// Your worker tells you in the message what to do.
}
};
So I am having issues with my AsyncTask. I need postExecute to display an alert dialog if a certain error throwable is caught in doInBackground. The problem is that postExecute is never called. I have tried adding #Override but Android Studio says that it isn't overriding a method in its super class. I have also tried changing the return type. I looked around this site and couldn't find an answer. Thanks in advance.
AsyncTask Class
public class AsyncTaskActivity extends AsyncTask<Void, Void, Void> {
String exception;
#Override
protected void onPreExecute() {
}
protected void onPostExecute() {
if (exception.contains("java.net.UnknownHostException")) {
MainActivity.showDialog();
Log.i("Error Message", "ERROR MESSAGE SHOWN");
}
}
#Override
protected Void doInBackground(Void... params) {
try {
Log.i("AsyncTask", "Loading...");
// Make a URL to the web page. This takes the string representation of the URL
// and changes it into a URL object
URL url = new URL("http://api.wunderground.com/api/0c0fcc3bf62ab910/conditions/q/IN/Fort_Wayne.json");
// Get the input stream through URL Connection
URLConnection con = url.openConnection();
InputStream is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
// read each line and write to text file
while ((line = br.readLine()) != null) {
Log.i("AsyncTask", line);
TextEditor.file = new File(MainActivity.path, "siteInfo.txt");
TextEditor.writeString(line);
}
TextEditor.saveAndClose();
} catch (Exception e) {
e.printStackTrace();
exception = e.toString();
}
Log.i("AsyncTask", "DONE");
return null;
}
}
showDialog method
public static void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.context);
builder.setView(R.layout.dialog_layout);
builder.setPositiveButton(
R.string.dialog_close,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
System.exit(1);
}
});
builder.show();
}
look like you're missing something
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (exception.contains("java.net.UnknownHostException")) {
MainActivity.showDialog();
Log.i("Error Message", "ERROR MESSAGE SHOWN");
}
}
First please refer this documentation. you have missed parameters on onPostExecute().
https://developer.android.com/reference/android/os/AsyncTask.html
What you would have to do is,
#Override
protected void onPostExecute(Params) {
// your logics
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (exception.contains("java.net.UnknownHostException")) {
MainActivity.showDialog();
Log.i("Error Message", "ERROR MESSAGE SHOWN");
}
}
Please note that you need to initialize exception, otherwise it may cause a NullPointerException
I'm creating an app in Android using Socket.IO. I am stuck at the Login itself. Here is my code for Login
public class MainActivity extends AppCompatActivity {
EditText uname_et, pwd_et;
Button log;
String username, password;
private Socket mSocket;
private Emitter.Listener onLogin = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(args[0].toString(), "data");
Log.w("yes ", "in evtLogin");
// JSONObject data = (JSONObject) args[0];
}
};
{
try {
String URL = "http://MYIP:8081";
mSocket = IO.socket(URL);
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uname_et = (EditText) findViewById(R.id.username_input);
pwd_et = (EditText) findViewById(R.id.pwd);
log = (Button) findViewById(R.id.sign_in_button);
log.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signin();
}
});
mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("Make Emit", "Emit");
Log.w(mSocket.connected() + " - ", "Connection status");
}
});
mSocket.on("evtLogin", onLogin);
mSocket.connect();
}
private void signin() {
username = uname_et.getText().toString();
password = pwd_et.getText().toString();
mSocket.emit("userName", username);
mSocket.emit("Password", password);
}
#Override
protected void onDestroy() {
super.onDestroy();
mSocket.off("evtLogin", onLogin);
}
}
I'm not sure that socket is even connected or not, I'm gettong logs from Socket.EVENT_CONNECT
08-31 12:22:22.062 13399-13441/com.fis.kotsocket I/Make Emit﹕ Emit
08-31 12:22:22.063 13399-13441/com.fis.kotsocket W/true -﹕ Connection status
But onLogin listener is not called.
As a newbie I am not sure what to do exactly.
js code
//code for login event
socket.on('evtLogin', function (loginData) {
console.log('loged');
User.findOne({'login.userName':loginData.userName,'login.password':loginData.password},function(err,user){
if(err){throw err;}
else {if(!user){
console.log('not a authenticated user');
}
else
{
var userType;
User.find({'login.userName':loginData.userName,'login.password':loginData.password},function(err,rslt){
if(err){throw err;}
else
{
userType = JSON.stringify(rslt[0]['userType'].userId);
socket.emit('evtUserType',userType);
}
})
}
}
});
console.log('done');
});
Your socket is not getting initialized.
Try this initialization:
private Socket mSocket;
{
try {
mSocket = IO.socket("enter url here");
} catch (URISyntaxException e) {}
}
Or it might be that you are not emitting the evtLogin event from your javascript code.
I want to make a TCP client that can sent and receive data for server. I use Hercules(TCP/UDP test program) as Server. My code can send string "Submit" to Server. I try to make my code can receive data from Hercules but it not work.what I have to do for edit it?
This is my MainActivity code
public class MainActivity extends Activity {
// Used to reference UI elements of main.xml
private TextView text,serverResponse;
private EditText ipBox;
private EditText portBox;
private ToggleButton connect;
private Button send;
private static final String TAG = "CClient";
private String ipAddress;
private Socket client;
private DataOutputStream outToServer;
private DataInputStream inFromServer;
private boolean connected = false;
private final int START = 0xffffff;
private final int msgBoxHint = START;
private final int appendText = START + 1;
Toast mytoast , savetoast;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Log.d(TAG, "Here 1");
ipAddress = getLocalIpAddress();
Log.d(TAG, "Get local IP="+ ipAddress);
text = (TextView) findViewById(R.id.text);
ipBox = (EditText) findViewById(R.id.ipBox);
serverResponse = (TextView) findViewById(R.id.response);
portBox = (EditText) findViewById(R.id.portBox);
send = (Button) findViewById(R.id.send);
send.setOnClickListener(buttonsendOnClickListener);
connect = (ToggleButton) findViewById(R.id.connect);
connect.setOnClickListener(buttonConnectOnClickListener);
Button buttonExit = (Button) findViewById(R.id.btnExit);
buttonExit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d(TAG, "Exit");
Log.d(TAG, "Disconnect" );
if(client != null)
{
try {
client.close();
} catch (IOException e) {
Log.d(TAG, "Disconnect"+e.toString() );
}
}
finish();
}
});
}
OnClickListener buttonConnectOnClickListener = new OnClickListener() {
/** Manages all button clicks from the screen */
#TargetApi(Build.VERSION_CODES.HONEYCOMB) #Override
public void onClick(View arg0) {
switch(arg0.getId())
{
case R.id.connect:
if(connect.isChecked())
{
Log.d(TAG, "Connect" );
EditText edIP = (EditText) findViewById(R.id.ipBox);
String ed_textIP = edIP.getText().toString().trim();
if(ed_textIP.isEmpty() || ed_textIP.length() == 0 || ed_textIP.equals("") || ed_textIP == null )
{
Toast.makeText(MainActivity.this, "IP Address or PORT is incorrect", Toast.LENGTH_SHORT).show();
Log.d(TAG, "IP Address or PORT is incorrect");
}
setValues(R.id.connect,true);
setValues(R.id.send,true);
setValues(R.id.ipBox,false);
String tMsg = welcomeMsg.toString();
MyClientTask myClientTask = new MyClientTask(ipBox
.getText().toString(), Integer.parseInt(portBox
.getText().toString()),
tMsg);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
myClientTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
myClientTask.execute();
}
else
{ /*Toast.makeText(this, ipBox.getText(), Toast.LENGTH_LONG).show();*/
Log.d(TAG, "Disconnect" );
if(client != null)
{
try {
client.close();
} catch (IOException e) {
Log.d(TAG, "Disconnect"+e.toString() );
}
setText(R.id.text,"Press the connect button to start the client");
setText(msgBoxHint,"");
setValues(R.id.connect,false);
setValues(R.id.ipBox,true);
setValues(R.id.send,false);
}
else
{
setValues(R.id.connect,false);
}
}
break;
}
}
};
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String response = "";
String msgToServer;
MyClientTask(String addr, int port, String msgTo) {
dstAddress = addr;
dstPort = port;
msgToServer = msgTo;
}
protected Void doInBackground(Void... Arg0) {
Log.d(TAG, "InBackground");
Socket socket = null;
DataOutputStream outToServer = null;
DataInputStream inFromServer = null;
try {
client = new Socket(dstAddress, dstPort);
outToServer = new DataOutputStream(client.getOutputStream());
inFromServer = new DataInputStream(new BufferedInputStream(client.getInputStream())); // Input stream <- from server
}catch (UnknownHostException e) {
// TODO Auto-generated catch block
Log.d(TAG, "InBackground 1");
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
mytoast = Toast.makeText(MainActivity.this, "Error UnknownHostException",
Toast.LENGTH_SHORT);
mytoast.show();
setValues(R.id.send,false);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mytoast.cancel();
}
}, 500);
}
});
} catch (IOException e) {
Log.d(TAG, "InBackground 2");
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
mytoast = Toast.makeText(MainActivity.this, "Error IOException",
Toast.LENGTH_SHORT);
mytoast.show();
setValues(R.id.connect,false);
setValues(R.id.send,false);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mytoast.cancel();
}
}, 500);
}
});
}finally {
Log.d(TAG, "InBackground 3");
if (socket != null) {
try {
socket.close();
Log.d(TAG, "InBackground 3.11");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d(TAG, "InBackground 3.12");
}
}
Log.d(TAG, "InBackground 3.1");
}
Log.d(TAG, "InBackground 4");
return null;
}
#Override
protected void onPostExecute(Void result) {
serverResponse.setText(response);
super.onPostExecute(result);
}
}
OnClickListener buttonsendOnClickListener = new OnClickListener() {
/** Manages all button clicks from the screen */
#TargetApi(Build.VERSION_CODES.HONEYCOMB) #Override
public void onClick(View arg0) {
switch(arg0.getId())
{
case R.id.send:
Log.d(TAG, "Sent" );
String sentence = "Submit";
String recieve = "";
serverResponse = (TextView) findViewById(R.id.response);
try {
outToServer = new DataOutputStream(client.getOutputStream());
inFromServer = new DataInputStream(new BufferedInputStream(client.getInputStream()));
Log.d(TAG, "Sent 1-1" );
if(sentence != null){
outToServer.writeUTF(sentence);
outToServer.flush();
}
/*
*
*
*
*
*
*/
Log.d(TAG, "Sent 1-2"+ recieve);
} catch (IOException e) {
setValues(R.id.ipBox,true);
setValues(R.id.connect,false);
setValues(R.id.send,false);
}
break;
}
}
};
private String getLocalIpAddress() {
Log.d(TAG, "Here 2");
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
Log.d(TAG, "Here 3");
WifiInfo info = wifi.getConnectionInfo();
Log.d(TAG, "Here 4");
return Formatter.formatIpAddress(info.getIpAddress());
}
private void setText(int view, String content)
{
switch(view)
{
case R.id.ipBox: ipBox.setText(content); break;
case R.id.text: text.setText(content+"\n\n"); break;
case appendText: text.append(content+"\n\n"); break;
}
}
private void setValues(int view, boolean value)
{
switch(view)
{
case R.id.ipBox: ipBox.setEnabled(value); break;
case R.id.send: send.setEnabled(value); break;
case R.id.connect: connect.setChecked(value); break;
}
}
}
I think, I have to add receive code in buttonsendOnClickListener near /*****/.
Do not work with sockets in main (gui) thread. Use AsyncTask!
Android fails if work with sockets in main (gui) thread.
Example:
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
// do in main thread before
}
#Override
protected Void doInBackground(Void... v) {
// do in thread, use sockets
return null;
}
#Override
protected void onPostExecute(Void v) {
super.onPostExecute(integer);
// do in main thread after
}
}.execute();
Learn about AsyncTask advance.
I am connecting two Android Devices P2P using the following code. The problem is that when the server receives data from client its Thread/Runnable doesn't stop.
Please suggest me a way to stop/forced this to go in an infinite loop.
Following Is the piece of code I am using for my Server Activity :
public class ServerThread implements Runnable {
private volatile boolean keepGoing = true;
public void requestStop() {
keepGoing = false;
}
public void run() {
try {
if (SERVERIP != null) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Listening on IP: " + SERVERIP);
}
});
serverSocket = new ServerSocket(SERVERPORT);
while (true) {
// listen for incoming clients
Socket client = serverSocket.accept();
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Connected.");
}
});
try {
BufferedReader in = new BufferedReader(new
InputStreamReader(client.getInputStream()));
line = null;
while ((line = in.readLine()) != null) {
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText(line);
Log.d("IP recevied", line);
requestStop();
//finish();
//Intent i = new Intent(ServerActivity.this,
//ClientActivity.class);
//startActivity(i);
//serverStatus.setText(line);
// do whatever you want to the front end
// this is where you can be creative
}
});
}
break;
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Oops. Connection interrupted.
Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
} else {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Couldn't detect internet connection.");
}
});
}
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Error");
}
});
e.printStackTrace();
}
}
}
EDIT:
while (keepGoing) {
// listen for incoming clients
Socket client = serverSocket.accept();
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Connected.");
}
});
try {
BufferedReader in = new BufferedReader(new
InputStreamReader(client.getInputStream()));
line = null;
while (((line = in.readLine()) != null) && keepGoing) {
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText(line);
Log.d("IP recevied", line);
requestStop();
//finish();
//Intent i = new Intent(ServerActivity.this,
//ClientActivity.class);
//startActivity(i);
//serverStatus.setText(line);
// do whatever you want to the front end
// this is where you can be creative
}
});
}
I think the problem is that even though you signal the server to stop, it's still stuck in the call to serverSocket.accept();, waiting for other clients to connect. What you should do is also close the socket in the stop method:
public void requestStop() {
keepGoing = false;
serverSocket.close();
}
to force the code to throw an IOException and then recheck the while condition and exit.
Why did you comment the line
//finish();
once the connection is established?
Since you never finish once you are connected you have an infinite loop