I've been struggling the whole day to make an Android client application. I managed to get the answer from the server but i can't properly display it in a text View. I did the app using other answers from here or Youtube videos.
The application should be really simple.Then i press a button, it sends a SQL query to the server and it returns some data from the database which should be displayed in a text View.
I'll post the code and then explain where the problem occurs:
public class MainActivity extends Activity
{
private TextView serverMessage;
private Thread thread;
private Socket clientSocket;
private String mesaj;
String answer = "";
String partial = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serverMessage = (TextView)findViewById((R.id.textView));
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onPause() {
super.onPause();
}
public void Start(View v)
{
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
clientSocket = new Socket("92.55.154.98", 100);
Log.d("Sending server", "SEnding " + "SELECT * FROM Pubs");
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true);
out.println("SELECT * FROM Pubs");
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((partial = in.readLine()) != null) {
answer= answer + partial +"\n" ;
Log.e("In while", answer);
}
in.close();
clientSocket.close();
Log.e("After while", answer);
Message answer = null;
answer.obj=answer;
handler.sendMessage(answer);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
answer="";
//serverMessage.setText(answer);
}
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg)
{ Log.w("Message recieved ?? ", msg.obj.toString());
messageDisplay(msg.obj.toString());
}
};
public void messageDisplay(String mesaj)
{
serverMessage.setText(mesaj);
}
}
The problem appears here in the Start method:
while ((partial = in.readLine()) != null) {
answer= answer + partial +"\n" ;
Log.e("In while", answer);
}
in.close();
clientSocket.close();
Log.e("After while", answer);
The log properly shows me the answer String just inside the while loop. After the while loop ends, nothing else from this method runs. It doesn't display the log that i placed after the while loop Log.e("After while", answer); I managed to show the second log just if i closed the server, but it crashed when it tried to run the rest of the code.
The result is somehow showed if i uncomment this part that's at the end of the Start method:
thread.start();
answer="";
//serverMessage.setText(answer);
In this case he result is only showed if i press the button twice !
Does anybody have an ideea why it acts like that and is there a solution ?
Instead of
Message answer = null;
answer.obj=answer;
handler.sendMessage(answer);
which is guaranteed to fail with a NullpointerException (if you make it compile) try
handler.obtainMessage(0, answer).sendToTarget();
Related
I'm a little bit confused....
I have the following method and my App is closing without a Force close dialog. And I don't know why. I think it should be all fine...
I can't give more information. If you want more, please ask me.
public void findCC3000(View view) {
new AsyncTask<String, Integer, String>() {
private ProgressDialog dialog;
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMax(64516);
dialog.setCancelable(false);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.dialog.setProgress(0);
this.dialog.show();
}
#Override
protected String doInBackground(String... strings) {
int port = Integer.valueOf(((EditText) MainActivity.this.findViewById(R.id.editText_port)).getText().toString());
String ip = ((EditText) MainActivity.this.findViewById(R.id.editText_ip)).getText().toString();
try {
out("try to connect");
socket = new Socket(ip, port);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println("");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String fromServer;
out("listen for message");
while ((fromServer = in.readLine()) != null) { //CRASH-------------------------------------------------------
out(fromServer);
if (fromServer.equals("Connected to CC3000")) {
out("CC3000 found! : " + ip);
//startListenThread();
out("Started Lissten thread " );
findViewById(R.id.button_connect).setEnabled(false);
findViewById(R.id.joystickView_geschwindigkeit).setEnabled(true);
findViewById(R.id.joystickView_lenkung).setEnabled(true);
return ip;
}
}
} catch (UnknownHostException e) {
out(e.getMessage());
} catch (IOException e) {
out(e.getMessage());
}
return "";
}
protected void onProgressUpdate(Integer... progress) {
dialog.setProgress(progress[0]);
}
protected void onPostExecute(String result) {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
if (result.isEmpty())
Toast.makeText(MainActivity.this, "CC3000 not found! :(", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "CC3000 found! :)", Toast.LENGTH_SHORT).show();
ip = result;
}
}.execute("192.168.");
}
But I know the place.
So the important part is (the readLine()):
while ((fromServer = in.readLine()) != null) { //CRASH-------------------------------------------------------
out(fromServer);
if (fromServer.equals("Connected to CC3000")) {
out("CC3000 found! : " + ip);
//startListenThread();
out("Started Lissten thread " );
findViewById(R.id.button_connect).setEnabled(false);
findViewById(R.id.joystickView_geschwindigkeit).setEnabled(true);
findViewById(R.id.joystickView_lenkung).setEnabled(true);
return ip;
}
}
This is my Logcat:
06-06 16:12:16.494 20152-20166/de.mayerhofersimon.cc3000.main
W/dalvikvm﹕ threadid=11: thread exiting with uncaught exception
(group=0x4155dce0)
Hope you can help.
regards
Only the UI Thread can touch the UI. You can take a look the implementation of setEnabled
4586 public void More ...setEnabled(boolean enabled) {
4587 if (enabled == isEnabled()) return;
4588
4589 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
4590
4591 /*
4592 * The View most likely has to change its appearance, so refresh
4593 * the drawable state.
4594 */
4595 refreshDrawableState();
4596
4597 // Invalidate too, since the default behavior for views is to be
4598 // be drawn at 50% alpha rather than to change the drawable.
4599 invalidate(true);
4600 }
I am writing an IRC Client. The socket connection to the IRC Server is handled via a service. I have managed to stabilize all the UI elements of the Activities in question during the orientation change, but somehow the socket that is maintained by the service is being closed during the change.
Here is what I believe to be the relevant code. Please let me know if you need to see more.
//This is the Service in question
public class ConnectionService extends Service{
private BlockingQueue<String> MessageQueue;
public final IBinder myBind = new ConnectionBinder();
public class ConnectionBinder extends Binder {
ConnectionService getService() {
return ConnectionService.this;
}
}
private Socket socket;
private BufferedWriter writer;
private BufferedReader reader;
private IRCServer server;
private WifiManager.WifiLock wLock;
private Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
try {
String line;
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
queueMessage(line);
}
}
catch (Exception e) {}
}
});
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(MessageQueue == null)
MessageQueue = new LinkedBlockingQueue<String>();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return myBind;
}
#Override
public boolean stopService(Intent name) {
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.stopService(name);
}
#Override
public void onDestroy()
{//I put this here so I had a breakpoint in place to make sure this wasn't firing instead of stopService
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onDestroy();
}
public void SendMessage(String message)
{
try {
writer.write(message + "\r\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readLine()
{
try {
if(!isConnected())
return null;
else
return MessageQueue.take();
} catch (InterruptedException e) {
return "";
}
}
public boolean ConnectToServer(IRCServer newServer)
{
try {
//create a new message queue (connecting to a new server)
MessageQueue = new LinkedBlockingQueue<String>();
//lock the wifi
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "LockTag");
wLock.acquire();
server = newServer;
//connect to server
socket = new Socket();
socket.setKeepAlive(true);
socket.setSoTimeout(60000);
socket.connect(new InetSocketAddress(server.NAME, Integer.parseInt(server.PORT)), 10000);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//run basic login scripts.
if(server.PASS != "")
SendMessage("PASS " + server.PASS);
//write nickname
SendMessage("NICK " + server.NICK);
//write username login
SendMessage("USER " + server.NICK + " 0 * :Fluffy IRC");
String line;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
//change to alt Nick
if(!server.NICK.equals(server.ALT_NICK) && !server.ALT_NICK.equals(""))
{
server.NICK = server.ALT_NICK;
SendMessage("NICK " + server.NICK);
}
else
{
queueMessage("Nickname already in use");
socket.close();
return false;
}
}
else if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
{
queueMessage(line);
}
}
//start the reader thread AFTER the primary login!!!
CheckStartReader();
if(server.START_CHANNEL == null || server.START_CHANNEL == "")
{
server.WriteCommand("/join " + server.START_CHANNEL);
}
//we're done here, go home everyone
} catch (NumberFormatException e) {
return false;
} catch (IOException e) {
return false;
}
return true;
}
private void queueMessage(String line) {
try {
MessageQueue.put(line);
} catch (InterruptedException e) {
}
}
public boolean isConnected()
{
return socket.isConnected();
}
public void CheckStartReader()
{
if(this.isConnected() && !readThread.isAlive())
readThread.start();
}
}
//Here are the relevant portions of the hosting Activity that connects to the service
//NOTE: THE FOLLOWING CODE IS PART OF THE ACTIVITY, NOT THE SERVICE
private ConnectionService conn;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
conn = ((ConnectionService.ConnectionBinder)service).getService();
Toast.makeText(main_tab_page.this, "Connected", Toast.LENGTH_SHORT)
.show();
synchronized (_serviceConnWait) {
_serviceConnWait.notify();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
conn = null;
}
};
#Override
protected void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
state.putParcelable("Server", server);
state.putString("Window", CurrentTabWindow.GetName());
unbindService(mConnection);
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(this.isFinishing())
stopService(new Intent(this, ConnectionService.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_tab_page);
localTabHost = (TabHost)findViewById(R.id.tabHostMain);
localTabHost.setup();
localTabHost.setOnTabChangedListener(new tabChange());
_serviceConnWait = new Object();
if(savedInstanceState == null)
{//initial startup, coming from Intent to start
//get server definition
server = (IRCServer)this.getIntent().getParcelableExtra(IRC_WINDOW);
server.addObserver(this);
AddTabView(server);
startService(new Intent(this, ConnectionService.class));
}
else
{
server = (IRCServer)savedInstanceState.getParcelable("Server");
String windowName = savedInstanceState.getString("Window");
//Add Needed Tabs
//Server
if(!(windowName.equals(server.GetName())))
AddTabView(server);
//channels
for(IRCChannel c : server.GetAllChannels())
if(!(windowName.equals(c.GetName())))
AddTabView(c);
//reset each view's text (handled by tabChange)
if(windowName.equals(server.GetName()))
SetCurrentTab(server.NAME);
else
SetCurrentTab(windowName);
ResetMainView(CurrentTabWindow.GetWindowTextSpan());
//Rebind to service
BindToService(new Intent(this, ConnectionService.class));
}
}
#Override
protected void onStart()
{
super.onStart();
final Intent ServiceIntent = new Intent(this, ConnectionService.class);
//check start connection service
final Thread serverConnect = new Thread(new Runnable() {
#Override
public void run() {
if(!BindToService(ServiceIntent))
return;
server.conn = conn;
conn.ConnectToServer(server);
server.StartReader();
if(server.START_CHANNEL != null && !server.START_CHANNEL.equals(""))
{
IRCChannel chan = server.FindChannel(server.START_CHANNEL);
if(chan != null)
{
AddTabView(chan);
}
else
{
server.JoinChannel(server.START_CHANNEL);
chan = server.FindChannel(server.START_CHANNEL);
AddTabView(chan);
}
}
}
});
serverConnect.start();
}
private boolean BindToService(Intent ServiceIntent)
{
int tryCount = 0;
bindService(ServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
while(conn == null && tryCount < 10)
{
tryCount++;
try {
synchronized (_serviceConnWait) {
_serviceConnWait.wait(1500);
}
}
catch (InterruptedException e) {
//do nothing
}
}
return conn != null;
}
Im not entirely certain what I am doing wrong there. Obviously there's something I'm missing, haven't found yet, or haven't even thought to check. What happens though is that after the orientation change my Send command gives me this message and nothing happens:
06-04 22:02:27.637: W/System.err(1024): java.net.SocketException: Socket closed
06-04 22:02:27.982: W/System.err(1024): at com.fluffyirc.ConnectionService.SendMessage(ConnectionService.java:90)
I have no idea when the socket is getting closed, or why.
Update
I have changed the code so that rather than binding to the service and using that to start it, instead I call startService and stopService at appropriate points as well as binding to it, on the thought that the service was being destroyed when the binding was lost. This is working exactly like it was before I changed it. The socket still closes on an orientation change, and I have no idea why.
Update :- Code and description
I added the code changes recently made for Start/Stop service and START_STICKY. I also recently read a very good article explaining how the orientation change process flow works and why its NOT a bad idea to add the android:configChanges="orientation|screenSize" line to your manifest. So this fixed the orientation issue, but its still doing the same thing if I put the activity into background mode, and then bring it back to the foreground. That still follows the same Save/Destroy/Create process that the orientation does without that manifest line...and it still closes my socket, and I still don't know why.
I do know that it doesn't close the socket until the re-create process...I know this because the message queue will display messages that were received while the app was in the background, but once I bring it back forward it closes the socket and nothing else can be sent or received.
'Socket closed' means that you closed the socket and then continued to use it. It isn't a 'disconnect'.
You need to put something into that catch block. Never just ignore an exception. You might get a surprise when you see what the exception actually was.
NB Socket.isConnected() doesn't tell you anything about the state of the connection: only whether you have ever connected the Socket. You have, so it returns true.
I added the AsyncTask to offload network operations to a background thread.I need to make sure the UI operations are on the UI thread.So i want to Use runOnUiThread() in my Activity.
Thanks for your help
WifiApManager
public class WifiApManager {
private final WifiManager mWifiManager;
public WifiApManager(Context context) {
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
try {
if (enabled) { // disable WiFi in any case
mWifiManager.setWifiEnabled(false);
}
Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
return (Boolean) method.invoke(mWifiManager, wifiConfig, enabled);
} catch (Exception e) {
Log.e(this.getClass().toString(), "wifi", e);
return false;
}
}
public WIFI_AP_STATE getWifiApState() {
try {
Method method = mWifiManager.getClass().getMethod("getWifiApState");
int tmp = ((Integer)method.invoke(mWifiManager));
// Fix for Android 4
if (tmp > 10) {
tmp = tmp - 10;
}
return WIFI_AP_STATE.class.getEnumConstants()[tmp];
} catch (Exception e) {
Log.e(this.getClass().toString(), "wifi", e);
return WIFI_AP_STATE.WIFI_AP_STATE_FAILED;
}
}
public boolean isWifiApEnabled() {
return getWifiApState() == WIFI_AP_STATE.WIFI_AP_STATE_ENABLED;
}
public WifiConfiguration getWifiApConfiguration() {
try {
Method method = mWifiManager.getClass().getMethod("getWifiApConfiguration");
return (WifiConfiguration) method.invoke(mWifiManager);
} catch (Exception e) {
Log.e(this.getClass().toString(), "wifi", e);
return null;
}
}
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
Method method = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
return (Boolean) method.invoke(mWifiManager, wifiConfig);
} catch (Exception e) {
Log.e(this.getClass().toString(), "wifi", e);
return false;
}
}
public ArrayList<ClientScanResult> getClientList(boolean onlyReachables) {
return getClientList(onlyReachables, 10);
}
public ArrayList<ClientScanResult> getClientList(boolean onlyReachables, int reachableTimeout) {
BufferedReader br = null;
ArrayList<ClientScanResult> result = null;
try {
result = new ArrayList<ClientScanResult>();
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if ((splitted != null) && (splitted.length >= 4)) {
// Basic sanity check
String mac = splitted[3];
if (mac.matches("..:..:..:..:..:..")) {
boolean isReachable = InetAddress.getByName(splitted[0]).isReachable(reachableTimeout);
if (!onlyReachables || isReachable) {
result.add(new ClientScanResult(splitted[0], splitted[3], splitted[5], isReachable));
}
}
}
}
} catch (Exception e) {
Log.e(LOGTAG, e.toString());
} finally {
try {
br.close();
} catch (IOException e) {
Log.e(LOGTAG, e.toString());
}
}
return result;
}
}
connect.java
public class connect extends Activity{
WifiApManager wifiApManager;
TextView tv;
Button scan;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.connect);
tv =(TextView) findViewById(R.id.iptv);
new scan().execute();
}
public class scan extends AsyncTask<String, Integer, String> {
public Object WIFI_SERVICE;
#Override
protected void onProgressUpdate(Integer...integers) {
ArrayList<ClientScanResult> clients = wifiApManager.getClientList(false);
tv.setText("WifiApState: " + wifiApManager.getWifiApState() + "\n\n");
tv.append("Clients: \n");
for (ClientScanResult clientScanResult : clients) {
tv.append("####################\n");
tv.append("IpAddr: " + clientScanResult.getIpAddr() + "\n");
tv.append("Device: " + clientScanResult.getDevice() + "\n");
tv.append("HWAddr: " + clientScanResult.getHWAddr() + "\n");
tv.append("isReachable: " + clientScanResult.isReachable()+ "\n");
}
}
#Override
protected void onPostExecute(String result){
tv.setText(result);
}
#Override
protected String doInBackground(String... params) {
wifiApManager = new WifiApManager(this);
// the above line shows a Error
return null;
}
}
}
EDIT
I want to Display the processed text in a TextView
class scan extends AsyncTask<String, Void, Void> {
public Context context;
ArrayList<ClientScanResult> clients;
public scan(Context c) // constructor to take Context
{
context = c; // Initialize your Context variable
}
protected Void doInBackground(String... params) {
wifiApManager = new WifiApManager(context); // use the variable here
clients = wifiApManager.getClientList(false);
return null;
}
}
protected void onPostExecute(Void result){
ArrayList<ClientScanResult> clients;
tv.setText("WifiApState: " + wifiApManager.getWifiApState() + "\n\n");
tv.append("Clients: \n");
for (ClientScanResult clientScanResult : clients)//showin error in clients
{
tv.append("####################\n");
tv.append("IpAddr: " + clientScanResult.getIpAddr() + "\n");
tv.append("Device: " + clientScanResult.getDevice() + "\n");
tv.append("HWAddr: " + clientScanResult.getHWAddr() + "\n");
tv.append("isReachable: " + clientScanResult.isReachable()+ "\n");
}
}
}
I added the AsyncTask to offload network operations to a background thread.I need to make sure the UI operations are on the UI thread.So i want to Use runOnUiThread() in my Activity.
Ugh! No!!! Every method of AsyncTask runs on the UI Thread except for doInBackground(). So do your network operations in doInBackground() and update the UI in onPostExecute() or in onProgressUpdate() by calling publishProgress() from doInBackground().
Do not use runOnUiThread() with AsyncTask. There is no reason, at least known to me, to use that with AsyncTask since it has methods that already run on the UI Thread. I have never seen it do anything but cause trouble.
You can either call publishProgress() from your loop and update your TextView in onProgressUpdate() or add the values to an ArrayList and update in onProgressUpdate().
Please read the docs several times. AsyncTask is a bit tricky at first but once you learn what it does then it can be a beautiful thing.
Edit
Create an instance of your AsyncTask and pass your Activity Context to it
Scan myScan = new scan(this); // pass the context to the constructor
myScan.execute();
Then create a constructor in your AsyncTask and have it accept a Context.
public class scan extends AsyncTask<String, Integer, String>
{
public Object WIFI_SERVICE;
public Context context; // Context variable
public scan(Context c) // constructor to take Context
{
context = c; // intialize your Context variable
}
Now use that variable
#Override
protected String doInBackground(String... params)
{
wifiApManager = new WifiApManager(context); // use the variable here
return null;
}
Another Edit
class scan extends AsyncTask<String, Void, Void> {
ArrayList<ClientScanResult> clients;
Context context;
...
then initialize your `clients` in `doInBackground()`
clients = wifiApManager.getClientList(false);
change onPostExecute() to not accept anything
protected void onPostExecute(Void result){
and put your code that updates the TextView in there.
You should not be accessing any UI elements within doInBackground, This method runs in background thread. What you should do is override onPostExecute() method and access your TextView there. onPostExecute runs in UI thread, so you don't need to call runOnUiThread()
I'm working on an android Quiz app with connection to a server over a socket. On the client side (Android device) I check in a while loop the answers which are given by a server (Java server). The connection and the receiving of the answer all goes good. The problem is that in my class to check for answers there's a bug. To give more information I will include a part of the code here:
public void startClient(){
checkValue = new Thread(new Runnable(){
#Override
public void run() {
try
{
final int PORT = 4444;
final String HOST = "192.168.1.118";
Socket SOCK = new Socket(HOST, PORT);
Log.e("success", "You connected to: " + HOST);
quizClient = new QuizClient(SOCK);
//Send the groupname to the list
PrintWriter OUT = new PrintWriter(SOCK.getOutputStream());
OUT.println(groupName);
OUT.flush();
Thread X = new Thread(quizClient);
X.start();
connected = true;
}
catch(Exception X)
{
Log.e("connection error", "Error: ", X);
}
}
});
checkValue.start();
}
public void testvalue(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
while(true){
if(message != null && !message.matches("")){
Thread.sleep(1000);
Log.e("receive", message);
buffer = message;
message = "";
Message msg = new Message();
String textTochange = buffer;
msg.obj = textTochange;
mHandler.sendMessage(msg);
Thread.sleep(3000);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String)msg.obj;
//call setText here
//String[] myStringArray = new String[];
value.clear();
String[] items = text.split(";");
for (String item : items)
{
value.add(item);
Log.e("message", item);
//System.out.println("item = " + item);
}
if(value.get(0).equals("1")){
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
question.setText("");
question.setText(value.get(2));
rad1.setText(value.get(3));
rad2.setText(value.get(4));
rad3.setText(value.get(5));
rad4.setText(value.get(6));
questionGroup.setVisibility(View.VISIBLE);
sendAnswer.setVisibility(View.VISIBLE);
} else if (value.get(0).equals("2")){
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
question.setText("");
question.setText(value.get(2));
answer.setVisibility(View.VISIBLE);
sendAnswer.setVisibility(View.VISIBLE);
} else
{
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
question.setText(text);
}
}
};
#Override
protected void onStop()
{
if (connected == true){
try {
quizClient.DISCONNECT();
} catch (IOException e) {
e.printStackTrace();
}
}
if(checkValue != null)
{
checkValue.interrupt();
}
super.onStop();
closeApplication();
}
So I make a new instance of this class (where I actually check the incoming stream of data)
public class QuizClient implements Runnable {
//Globals
Socket SOCK;
Scanner INPUT;
Scanner SEND = new Scanner(System.in);
PrintWriter OUT;
public QuizClient(Socket X)
{
this.SOCK = X;
}
public void run()
{
try
{
try
{
INPUT = new Scanner(SOCK.getInputStream());
OUT = new PrintWriter(SOCK.getOutputStream());
OUT.flush();
CheckStream();
}
finally
{
SOCK.close();
}
}
catch(Exception X)
{
Log.e("error", "error: ", X);
}
}
public void DISCONNECT() throws IOException
{
OUT.println("DISCONNECT");
OUT.flush();
SOCK.close();
}
public void CheckStream()
{
while(true)
{
RECEIVE();
}
}
public void RECEIVE()
{
if(INPUT.hasNext())
{
String MESSAGE = INPUT.nextLine();
if(MESSAGE.contains("#?!"))
{
}
else
{
QuizActivity.message = MESSAGE;
Log.e("test", MESSAGE);
}
}
}
public void SEND(String X)
{
OUT.println(X);
OUT.flush();
}
}
So the bug persist I think in the following class:
public void testvalue(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
while(true){
if(message != null && !message.matches("")){
Thread.sleep(1000);
Log.e("receive", message);
buffer = message;
message = "";
What I do here is make a thread and check if the "message" is not equals at null. The message come from the other class:
public void RECEIVE()
{
if(INPUT.hasNext())
{
String MESSAGE = INPUT.nextLine();
if(MESSAGE.contains("#?!"))
{
}
else
{
QuizActivity.message = MESSAGE;
Now most of the time this works good but there are 2 problems. When I go out of the page it disconnect from the server (works) I go back on the page and connect again to the server but this time I don't get any values on the screen (receiving is okj but for one of the other reason it does not go good in my handler). Also get an indexoutofboundexception after a time:
question.setText(value.get(2));
A second problem occurs some time while the program runs. There are moments that I also don't get a value on my interface while it correctly receive the input.
So my guess is that my solution of the thread to read in the values is not the best way to handle it. So now I ask to people with more experience what I can do to make this work without major problems? You need to know the connection works and I get the value in my QuizClient class. So the problem need to be in my main class.
My oncreate class:
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
selectgroep = (Spinner) findViewById(R.id.groepen);
questionGroup = (RadioGroup) findViewById(R.id.QuestionGroup);
sendAnswer = (Button) findViewById(R.id.sendAnswer);
rad1 = (RadioButton) findViewById(R.id.radio0);
rad2 = (RadioButton) findViewById(R.id.radio1);
rad3 = (RadioButton) findViewById(R.id.radio2);
rad4 = (RadioButton) findViewById(R.id.radio3);
answer = (EditText) findViewById(R.id.textanswer);
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
try {
connect();
} catch (InterruptedException e) {
e.printStackTrace();
}
//Code na het drukken op de knop
startserver = (Button) findViewById(R.id.startserver);
startserver.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startClient();
getID();
testvalue();
}
});
sendAnswer.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Stuur antwoord door en sluit alles af
questionGroup.setVisibility(View.INVISIBLE);
sendAnswer.setVisibility(View.INVISIBLE);
answer.setVisibility(View.INVISIBLE);
answer.setText("");
rad1.setChecked(true);
rad1.setText("");
rad2.setText("");
rad3.setText("");
rad4.setText("");
question.setText("Wachten op server ... ");
}
});
}
Thank you in advance,
Thomas Thooft
I have got huge problem with my Android app and I would like to ask you for help.
I am currently writing Android Clietn-Server app using sockets. I have found lots of tutorils on the Internet and from them I have created basics for my project. However, all tutorials are only for one message send and that's all. I need to send more of them so I've been trying to modify it.
This are code fragments responsible for server and client. The rest is not important at this time.
Server:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverStatus = (TextView) findViewById(R.id.server_status);
recivedMsg = (TextView)findViewById(R.id.rec_msg);
SERVERIP = getLocalIpAddress();
Thread fst = new Thread(new ServerThread());
fst.start();
}
public class ServerThread implements Runnable {
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." + System.getProperty("line.separator"));
}
});
try {
line = null;
while (connected) {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
if((line = in.readLine())!=null)
{
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
if(recivedMsg.equals("CLOSE"))
{
recivedMsg.append("CLOSE socket");
connected = false;
}
else
{
recivedMsg.append("MSG: " + line + System.getProperty("line.separator"));
}
// do whatever you want to the front end
// this is where you can be creative
}
});
}
else
{
recivedMsg.append("empty" + System.getProperty("line.separator"));
}
}
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();
}
}
}
Client
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
sendField = (EditText) findViewById(R.id.send_field);
sendMsg = (Button) findViewById(R.id.msg_send);
connectPhones.setOnClickListener(connectListener);
sendMsg.setOnClickListener(sendMessage);
}
#Override
protected void onStop() {
super.onStop();
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "CLOSE";
out.write(outMsg);
out.flush();
// make sure you close the socket upon exiting
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private OnClickListener connectListener = new OnClickListener() {
#Override
public void onClick(View v) {
serverIpAddress = serverIp.getText().toString();
runTcpConnection();
sendMessageToServer("Msg");
}
};
private OnClickListener sendMessage = new OnClickListener() {
#Override
public void onClick(View v) {
sendMessageToServer(sendField.getText().toString());
}
};
private void runTcpConnection() {
try {
s = new Socket(serverIpAddress, SERVERPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "TCP connecting to " + SERVERPORT + System.getProperty("line.separator");
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
SystemClock.sleep(10);
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
};
public void sendMessageToServer(String str) {
try {
s = new Socket(serverIpAddress, SERVERPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = str + System.getProperty("line.separator");
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "hello222");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "hello4333");
}
}
For now devices connect correctly. Moreover They are sending the first connection messages (those in OnClickListener connectListener). The problem is that when I am trying to send another message using sendMessageToServer it is impossible. Those messages shows only after client activity is destroyed.
Very interesting is that without SystemClock.sleep(10); listener runTcpConnection() behave strange. Only 'Connected.' displays on server.
Can someone tell me what I have to do to be able to send messages normally?
EDIT:
This are things that I have found:
If I am at the connection sending more messages than all are empty (null) and after the second one connection error shows - please reconnect phones
If I am at the connection sending more messages without s.close line in sendMessageToServer only one message is passing through. No error is displayed after it.
The message form runTcpConnection shows always (except when in this function is no SystemClock.sleep(10))
Hope it will help someone to diagnose my error.
As I see, you create a new socket whenever user click button send, right? I recommend you should init it only one time when user click connect, then you use it in send click event ( because this is TCP, you will disconnect to server if you create new instance of socket)
So, you should remove these lines in sendMessageToServer :
s = new Socket(serverIpAddress, SERVERPORT);
s.close();
and this line in runTcpConnection
s.close();
Socket should close whenever you don't want communicate with the server (onstop is an example, or when change activity...)
Also you should create only one instance of BufferedWriter too.
Hope this help.