3 Threads + 3 Handlers don't work - android

I have 3 threads and 1 handler in each thread. But it only works one, the other 2 handlers clear the textview completely.
Code:
Thread getServerStatus = new Thread() {
public void run() {
Document doc;
try {
doc = dereference("my url");
String text = doc.select("div#serverstatus").toString();
Message msg = handler_serverstatus.obtainMessage();
msg.obj = text;
handler_serverstatus.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
Handler handler_serverstatus = new Handler()
{
public void handleMessage(Message msg)
{
String text = (String)msg.obj;
TextView tv = (TextView)findViewById(R.id.server_status);
if(text.contains("online")) {
//tv.setTextColor(2);
tv.setText("online");
} else if(text.contains("offline")) {
tv.setText("offline");
} else {
tv.setText("Error #1");
}
}
};
};
Thread getPlayersOnline = new Thread() {
public void run() {
Document doc;
try {
doc = dereference("my url");
String text = doc.select("div#players_on").toString();
Message msg = handler_players.obtainMessage();
msg.obj = text;
handler_players.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
Handler handler_players = new Handler()
{
public void handleMessage(Message msg)
{
String text = (String)msg.obj;
TextView tv = (TextView)findViewById(R.id.players_online);
text = text.replace("<div id=\"players_on\">", "");
text = text.replace("</div>", "");
tv.setText(text);
}
};
};
Thread getPlayersMax = new Thread() {
public void run() {
Document doc;
try {
doc = dereference("url");
String text = doc.select("div#players_max").toString();
Message msg = handler_players_max.obtainMessage();
msg.obj = text;
handler_players_max.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
Handler handler_players_max = new Handler()
{
public void handleMessage(Message msg)
{
String text = (String)msg.obj;
TextView tv = (TextView)findViewById(R.id.players_max);
text = text.replace("<div id=\"players_max\">", "");
text = text.replace("</div>", "");
tv.setText(text);
}
};
};
public void ButtonClick(View view) throws IOException {
getServerStatus.start();
getPlayersOnline.start();
getPlayersMax.start();
}
private Document dereference(String uri) throws IOException {
Connection connection = Jsoup.connect(uri);
return connection.get();
}
Is this maybe totally wrong?

Use
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1); // number of working thread
Runnable getServerStatus = new Runnable() {
#Override
public void run() {
Document doc;
try {
doc = dereference("my url");
String text = doc.select("div#serverstatus").toString();
Message msg = handler_serverstatus.obtainMessage();
msg.obj = text;
handler_serverstatus.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
Handler handler_serverstatus = new Handler()
{
public void handleMessage(Message msg)
{
String text = (String)msg.obj;
TextView tv = (TextView)findViewById(R.id.server_status);
if(text.contains("online")) {
//tv.setTextColor(2);
tv.setText("online");
} else if(text.contains("offline")) {
tv.setText("offline");
} else {
tv.setText("Error #1");
}
}
};
};
Runnable getPlayersOnline = new Runnable() {
#Override
public void run() {
Document doc;
try {
doc = dereference("my url");
String text = doc.select("div#players_on").toString();
Message msg = handler_players.obtainMessage();
msg.obj = text;
handler_players.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
Handler handler_players = new Handler()
{
public void handleMessage(Message msg)
{
String text = (String)msg.obj;
TextView tv = (TextView)findViewById(R.id.players_online);
text = text.replace("<div id=\"players_on\">", "");
text = text.replace("</div>", "");
tv.setText(text);
}
};
}
Runnable getPlayersMax = new Runnable() {
public void run() {
Document doc;
try {
doc = dereference("url");
String text = doc.select("div#players_max").toString();
Message msg = handler_players_max.obtainMessage();
msg.obj = text;
handler_players_max.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
Handler handler_players_max = new Handler()
{
public void handleMessage(Message msg)
{
String text = (String)msg.obj;
TextView tv = (TextView)findViewById(R.id.players_max);
text = text.replace("<div id=\"players_max\">", "");
text = text.replace("</div>", "");
tv.setText(text);
}
};
};
newFixedThreadPool.submit(getServerStatus);
newFixedThreadPool.submit(getPlayersOnline);
newFixedThreadPool.submit(getPlayersMax); // submit all your targets
}
public void ButtonClick(View view) throws IOException {
newFixedThreadPool.shutdown();// shutdown and execute it
}
with 3 runnable inside;
Read tutorial about ThreadPools http://www.vogella.com/articles/JavaConcurrency/article.html, http://www.caveofprogramming.com/java/java-multithreading-thread-pools-video-tutorial-part/
or wrap your run() targets with synchronized block{};

Related

Unable to receive data from python server in an Android emulator client

I am trying to write a python (sockets) based server and an Android client, but while
sending data from the server to the client, the client doesn't receive any data. The server receives data from the client.
I think that the problem is possibly with the emulator, and not with the server because I did established a connection and the messages from the server may be blocked by the emulator's firewall.
Here is the code:
Client:
public class MainActivity extends AppCompatActivity {
Thread Thread1 = null;
EditText etIP, etPort;
TextView tvMessages;
EditText etMessage;
Button btnSend;
String SERVER_IP;
int SERVER_PORT;
Boolean done = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etIP = findViewById(R.id.etIP);
etPort = findViewById(R.id.etPort);
tvMessages = findViewById(R.id.tvMessages);
etMessage = findViewById(R.id.etMessage);
btnSend = findViewById(R.id.btnSend);
Button btnConnect = findViewById(R.id.btnConnect);
btnConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
done = false;
tvMessages.setText("");
SERVER_IP = etIP.getText().toString().trim();
SERVER_PORT = Integer.parseInt(etPort.getText().toString().trim());
Thread1 = new Thread(new Thread1());
Thread1.start();
}
});
btnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String message = etMessage.getText().toString().trim();
if (!message.isEmpty()) {
if(! done) {
String android_id= Settings.Secure.getString(MainActivity.this.getContentResolver(),
Settings.Secure.ANDROID_ID);
new Thread(new Thread3(android_id)).start();
done = true;
}
new Thread(new Thread3(message)).start();
}
}
});
}
private PrintWriter output;
private BufferedReader input;
class Thread1 implements Runnable {
public void run() {
Socket socket;
try {
socket = new Socket(SERVER_IP, SERVER_PORT);
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
runOnUiThread(new Runnable() {
#Override
public void run() {
tvMessages.setText("Connected\n");
}
});
new Thread(new Thread2()).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Thread2 implements Runnable {
#Override
public void run() {
while (true) {
try {
final String message = input.readLine();
if (message != null) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tvMessages.append("server: " + message + "\n");
}
});
} else {
Thread1 = new Thread(new Thread1());
Thread1.start();
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Thread3 implements Runnable {
private String message;
Thread3(String message) {
this.message = message;
}
#Override
public void run() {
output.write(message);
output.flush();
runOnUiThread(new Runnable() {
#Override
public void run() {
tvMessages.append("client: " + message + "\n");
etMessage.setText("");
}
});
}
}
}
Server:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
Thanks
This unidirectional behaviour, client -> server works, where as server -> client does not, is caused by the fact that the emulator is NAT-ed and most likely you have to set a rule to forward the inbound traffic (from a localhost port) to a local port of the emulator.
More info and examples here.

Message is displayed two times after using notifyDataSetChanged

I am working on an instant chat application.My problem is that when i am sending message through my chat application,Message is displayed two times instead of one.Screen shot is given below :
As you can see in the acreenshot that the message hiii is displayed two times but i have sent only once.
1.Adapter_Message.java
public class Adapter_Message extends BaseAdapter {
private Context context;
private List<Bean_Message> messagesItems;
public Adapter_Message(Context context, List<Bean_Message> navDrawerItems) {
this.context = context;
this.messagesItems = navDrawerItems;
}
#Override
public int getCount() {
return messagesItems.size();
}
#Override
public Object getItem(int position) {
return messagesItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#SuppressLint("InflateParams")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Bean_Message m = messagesItems.get(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
// Identifying the message owner
if (messagesItems.get(position).isSelf()) {
// message belongs to you, so load the right aligned layout
convertView = mInflater.inflate(R.layout.list_item_message_right, null);
} else {
// message belongs to other person, load the left aligned layout
convertView = mInflater.inflate(R.layout.list_item_message_left, null);
}
TextView lblFrom = (TextView) convertView.findViewById(R.id.lblMsgFrom);
TextView txtMsg = (TextView) convertView.findViewById(R.id.txtMsg);
txtMsg.setText(m.getMessage());
lblFrom.setText(m.getFromName());
return convertView;
}
}
2.Chat_Activity.java
public class ChatActivity extends FragmentActivity implements
EmojiconGridFragment.OnEmojiconClickedListener, EmojiconsFragment.OnEmojiconBackspaceClickedListener {
public static final String TAG = ChatActivity.class.getSimpleName();
// EditText edMessage;
EmojiconEditText edMessage;
Button sendMessage;
private Socket mSocket;
String sID, lID, md5StringRoomID, message, friendName, loggedInUser;
String frndID;
int smallerID, largerID;
//AlmaChatDatabase almaChatDatabase;
// Chat messages list adapter
private Adapter_Message adapter;
private List<Bean_Message> listBeanMessages;
private ListView listViewMessages;
boolean isSelf; // to check whether the message is owned by you or not.true means message is owned by you .
Bean_Message msg;
int loggedInUserID;
private String URL_FEED_Message = "";
APIConfiguration apiConfiguration;
SharedPreferences preferences;
HashMap<String, Integer> emoticons;
// instance initialization block
{
try {
mSocket = IO.socket(Constants.CHAT_SERVER_URL);
Log.e("Socket", String.valueOf(mSocket));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
sendMessage = (Button) findViewById(R.id.btnSendMessage);
preferences = getApplicationContext().getSharedPreferences(Prefs_Registration.prefsName, Context.MODE_PRIVATE);
//Handling emoticons
/* emoticons = new HashMap<String,Integer>();
emoticons.put(":-)",R.drawable.s1);*/
String id = preferences.getString(Prefs_Registration.get_user_id, null);
// Converting String id to integer
loggedInUserID = Integer.parseInt(id);
//loggedInUserID = almaChatDatabase.getUserID(); // Getting ID of the Logged in user from the database
Log.e("UserID", "Id of Logged in user " + loggedInUserID);
listBeanMessages = new ArrayList<Bean_Message>();
adapter = new Adapter_Message(getApplicationContext(), listBeanMessages);
listViewMessages = (ListView) findViewById(R.id.list_view_messages);
listViewMessages.setAdapter(adapter);
// Getting the ID of the friend from the previous screen using getExtras
Bundle bundle = getIntent().getExtras();
frndID = bundle.getString("ID");
Log.e("FriendID", frndID);
final int friendID = Integer.parseInt(frndID);
friendName = bundle.getString("name");
Log.e("FriendName", friendName);
loggedInUser = preferences.getString(Prefs_Registration.get_user_name, null);
//loggedInUser = almaChatDatabase.getUserName(); // Name of logged in user
Log.e("LoggedInUser", loggedInUser);
// Converting first lowercase letter of every word in Uppercase
final String loggedInUpper = upperCase(loggedInUser);
//To find the current time
Date d = new Date();
final long time = d.getTime();
// Comparing the loggedInUserId and friendID
if (friendID < loggedInUserID) {
smallerID = friendID;
largerID = loggedInUserID;
} else {
smallerID = loggedInUserID;
largerID = friendID;
}
sID = String.valueOf(smallerID);
lID = String.valueOf(largerID);
String combinedID = sID + lID;
Log.e("combined ID", combinedID);
md5StringRoomID = convertPassMd5(combinedID); // Encrypting the combinedID to generate Room ID
Log.e("md5StringRoomID", md5StringRoomID);
// Using the API for loading old chat messages
apiConfiguration = new APIConfiguration();
String api_message = apiConfiguration.getApi_message(); // Getting the API of messages
URL_FEED_Message = api_message + md5StringRoomID; // md5String is the encrypted room ID here
Log.e("URL_FEED_MESSAGE", URL_FEED_Message);
Log.e("Network request", "Fresh Request");
// We first check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Cache.Entry entry = cache.get(URL_FEED_Message);
if (entry != null) {
// fetch the data from cache
try {
String data = new String(entry.data, "UTF-8");
try {
parseJsonFeed(new JSONArray(data));
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(URL_FEED_Message, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray jsonArray) {
Log.e("JsonArray", String.valueOf(jsonArray));
if (jsonArray != null) {
parseJsonFeed(jsonArray);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.e("ErrorResponse", String.valueOf(volleyError));
}
}
);
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonArrayRequest);
}
edMessage = (EmojiconEditText) findViewById(R.id.edtMessage);
//Listening on Events
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectionError);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.on("send:notice", onReceive); // Listening event for receiving messages
mSocket.connect(); // Explicitly call connect method to establish connection here
mSocket.emit("subscribe", md5StringRoomID);
sendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
message = edMessage.getText().toString().trim();
Log.e("Sending", "Sending data-----" + message);
if (!message.equals("")) {
edMessage.setText(" ");
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("room_id", md5StringRoomID);
jsonObject.put("user", loggedInUpper);
jsonObject.put("id", friendID);
jsonObject.put("message", message);
jsonObject.put("date", time);
jsonObject.put("status", "sent");
} catch (JSONException e) {
e.printStackTrace();
}
isSelf = true; // Boolean isSelf is set to be true as sender of the message is logged in user i.e. you
attemptToSend(loggedInUpper, message, isSelf);
mSocket.emit("send", jsonObject); // owner i.e LoggedIn user is sending the message
} else {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Please enter some text", Toast.LENGTH_LONG).show();
}
});
}
}
});
setEmojiconFragment(false);
}
/* public Spannable getSmiledText(String text) {
SpannableStringBuilder builder = new SpannableStringBuilder(text);
if (emoticons.size() > 0) {
int index;
for (index = 0; index < builder.length(); index++) {
if (Character.toString(builder.charAt(index)).equals(":")) {
for (Map.Entry<String, Integer> entry : emoticons.entrySet()) {
int length = entry.getKey().length();
if (index + length > builder.length())
continue;
if (builder.subSequence(index, index + length).toString().equals(entry.getKey())) {
builder.setSpan(new ImageSpan(getApplicationContext(), entry.getValue()), index, index + length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
index += length - 1;
break;
}
}
}
}
}
return builder;
}*/
private void setEmojiconFragment(boolean useSystemDefault) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.emojicons, EmojiconsFragment.newInstance(useSystemDefault))
.commit();
}
//Adding message in the arrayList
public void attemptToSend(String senderName, String message, boolean isSelf) {
msg = new Bean_Message(senderName, message, isSelf);
listBeanMessages.add(msg);
adapter.notifyDataSetChanged();
playBeep();
}
// Playing sound when the message is sent by the owner
public void playBeep() {
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
// encrypting string into MD5
public static String convertPassMd5(String pass) {
String password = null;
MessageDigest mdEnc;
try {
mdEnc = MessageDigest.getInstance("MD5");
mdEnc.update(pass.getBytes(), 0, pass.length());
pass = new BigInteger(1, mdEnc.digest()).toString(16);
while (pass.length() < 32) {
pass = "0" + pass;
}
password = pass;
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
return password;
}
// Converting first lowercase letter of every word in Uppercase
String upperCase(String source) {
StringBuffer res = new StringBuffer();
String[] strArr = source.split(" ");
for (String str : strArr) {
char[] stringArray = str.trim().toCharArray();
stringArray[0] = Character.toUpperCase(stringArray[0]);
str = new String(stringArray);
res.append(str).append(" ");
}
return res.toString().trim();
}
// Event Listeners
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Socket", "Connected");
}
};
private Emitter.Listener onConnectionError = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Error", "Error in connecting server");
}
};
private Emitter.Listener onDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e("Disconnect", "Socket Disconnected");
}
};
// Event Listener for receiving messages
private Emitter.Listener onReceive = new Emitter.Listener() {
#Override
public void call(final Object... args) {
Log.e("Receive", "Bean_Message received");
runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
Log.e("DATA", String.valueOf(data));
try {
JSONArray ops = data.getJSONArray("ops");
for (int i = 0; i < ops.length(); i++) {
JSONObject object = ops.getJSONObject(i);
String roomID = object.getString("room_id");
Log.e("RoomID", roomID); // Getting room ID from JSON array
Log.e("Md5RoomID", md5StringRoomID); // Getting room id which we have created using logged in user ID and room id of the user through which chat has to be done
//Comparing the room IDs
if (md5StringRoomID.equals(roomID)) {
String senderName = object.getString("user");
Log.e("Sender Name", senderName);
String senderID = object.getString("id");
Log.e("SenderID", senderID);
// JSONObject message = object.getJSONObject("message");
String messageReceived = object.getString("message");
Log.e("Bean_Message Received", messageReceived);
String loggedInUSerNAme = preferences.getString(Prefs_Registration.get_user_name, null);
//String loggedInUSerNAme = almaChatDatabase.getUserName();
//If the message is sent by the owner to other from webapp ,then we need to check whether the sender is the loggedinUSer in the App or not and we will right align the messages .
if (loggedInUSerNAme.equalsIgnoreCase(senderName)) {
isSelf = true;
msg = new Bean_Message(senderName, messageReceived, isSelf);
listBeanMessages.add(msg);
// Log.e("List Elements", String.valueOf(listBeanMessages));
adapter.notifyDataSetChanged();
playBeep();
} else {
isSelf = false;
msg = new Bean_Message(senderName, messageReceived, isSelf);
listBeanMessages.add(msg);
Log.e("List Elements", String.valueOf(listBeanMessages));
adapter.notifyDataSetChanged();
playBeep();
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
// Playing sound when the message is sent by other
public void playBeep() {
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
};
// Parsing JSon Array which corresponds to the old chat messages
public void parseJsonFeed(JSONArray jsonArray) {
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String roomID = jsonObject.getString("room_id");
Log.e("RoomID", roomID);
Log.e("Md5RoomID", md5StringRoomID);
// If Room ID(created using id of logged in user and id of friend) matches with the room id obtained from JSON String
if (md5StringRoomID.equals(roomID)) {
String userName = jsonObject.getString("user");
Log.e("Name", userName);
String loggedInUSerNAme = preferences.getString(Prefs_Registration.get_user_name, null);
//String loggedInUSerNAme = almaChatDatabase.getUserName();
Log.e("LoggedInUSer", loggedInUSerNAme);
//If the message is sent by the owner to other from webapp ,then we need to check whether the sender is the loggedinUSer in the App or not and we will right align the messages .
if (loggedInUSerNAme.equalsIgnoreCase(userName)) {
String message = jsonObject.getString("message");
Log.e("message", message);
isSelf = true;
msg = new Bean_Message(userName, message, isSelf);
listBeanMessages.add(msg);
adapter.notifyDataSetChanged();
//playBeep();
} else {
JSONObject jsonMessage = jsonObject.getJSONObject("message");
String message = jsonMessage.getString("text");
isSelf = false;
msg = new Bean_Message(userName, message, isSelf);
listBeanMessages.add(msg);
adapter.notifyDataSetChanged();
// playBeep();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
// notify data changes to list adapter
//adapter.notifyDataSetChanged();
}
}
#Override
public void onEmojiconBackspaceClicked(View view) {
EmojiconsFragment.backspace(edMessage);
}
#Override
public void onEmojiconClicked(Emojicon emojicon) {
EmojiconsFragment.input(edMessage, emojicon);
}
}
3.Bean_Message.java
public class Bean_Message {
private String fromName, message;
private boolean isSelf; // isSelf is used to check whether the message is owned by you or not
public Bean_Message() {
}
public Bean_Message(String fromName, String message, boolean isSelf) {
this.fromName = fromName;
this.message = message;
this.isSelf = isSelf;
}
public String getFromName() {
return fromName;
}
public void setFromName(String fromName) {
this.fromName = fromName;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isSelf() {
return isSelf;
}
public void setSelf(boolean isSelf) {
this.isSelf = isSelf;
}
}
On clicking "Send Message" button ,message is sent to he server and the following code is used:
public void attemptToSend(String senderName, String message, boolean isSelf) {
msg = new Bean_Message(senderName, message, isSelf);
listBeanMessages.add(msg);
adapter.notifyDataSetChanged();
playBeep();
}
Message is stored in the Bean and Bean is added in the ArrayList .Now i am notifying my adapter that the ArrayList is updated using adapter.notifyDataSetChanged() method.But the problem is List view is displaying my sent message two times.Please help me to solve the issue .

Problems in change text of a textview

I have a problem in change a text of a textview in android, i'm starting in android, ok I want do a chat with sockets, I made the socket and connected on server but i can't change the text of the textview, ok this is the code:
public class Cliente extends Activity {
Button conect;
Button env;
EditText ip;
EditText nome;
EditText msg;
String nome_txt;
String ip_txt;
Socket cl;
String texto = "";
TextView log;
boolean a = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_layout);
conect = (Button) findViewById(R.id.conect);
env = (Button) findViewById(R.id.env);
msg = (EditText) findViewById(R.id.msg);
ip = (EditText) findViewById(R.id.ip_tx);
nome = (EditText) findViewById(R.id.nm_tx);
log = (TextView) findViewById(R.id.log);
conect.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
ip_txt = ip.getText().toString();
nome_txt = nome.getText().toString();
setContentView(R.layout.activity_cliente);
Thread th =new Thread(new Ct());
Log.d("Iniciado", "th");
log.setText("asd");
th.start();
}
});
env.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
try {
envMSG(msg.getText().toString());
msg.setText("");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public void envMSG(String msg) throws IOException {
DataOutputStream outToServer = new DataOutputStream(cl.getOutputStream());
outToServer.writeBytes(msg + '\n');
}
public String serOUT() {
try{
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(cl.getInputStream()));
if (inFromServer.ready()) {
String texto = inFromServer.readLine();
return texto;
} else {
return null;
}
}catch(IOException e){
return null;
}
}
public class Ct extends Thread implements Runnable{
#Override
public void run() {
try {
cl = new Socket(ip_txt, 1111);
envMSG(nome_txt);
do{
String tx = serOUT();
if (tx != null) {
texto += tx + "\n";
log.setText(texto);
envMSG("ola");
}
Log.d("Status",cl.isClosed()+"");
this.sleep(10);
}while (true);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Please tell the error reason, and show examples.
Thanks for Reading.
ass.:Lucas Avelino
First of all, you cant set text inside thread, you have to ovveride runOnUiThread method and try to set text in this method.
public class Ct extends Thread implements Runnable{
#Override
public void run() {
try {
cl = new Socket(ip_txt, 1111);
envMSG(nome_txt);
do{
String tx = serOUT();
if (tx != null) {
runOnUiThread(new Runnable() {
#Override
public void run() {
texto += tx + "\n";
log.setText(texto);
envMSG("ola");
}
});
}
Log.d("Status",cl.isClosed()+"");
this.sleep(10);
}while (true);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

How to wait a thread to be finished

Thread b = new Thread(new Runnable() {
#Override
public void run() {
try {
location = relocation();
//log("location success");
} catch (Exception e) {
e.printStackTrace();
}
}
});
b.start();
b.join();
if (location.y>0)
{
location_home.x = 4.5f;
location_home.y = 4.5f;
location_home.theta = (float)Math.PI;
} else
{
location_home.x = -4.5f;
location_home.y = -4.5f;
location_home.theta = 0;
}
I used b.join() to wait a time until var location receive value from relocation to define value for location_home. But its wrong. thread b and if statement running simultaneously. Help me :( tks all
i think it would be good if you use Asyntask in this case:
private class YourThread extends AsyncTask {
#Override
protected Object doInBackground(Object[] params) {
try {
location = relocation();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
//log("location success");
if (location.y > 0) {
location_home.x = 4.5f;
location_home.y = 4.5f;
location_home.theta = (float) Math.PI;
} else {
location_home.x = -4.5f;
location_home.y = -4.5f;
location_home.theta = 0;
}
}
}
and use it :
new YourThread().execute();

error: Only the original thread that created a view hierarchy can touch its views

Hi and thank you for looking at my question.
I am an intermediate programmer in C but an Android newbie. I have been trying to get a chat programming working. Assuming everything else in the code below works perfectly. The one question I like to ask is when I try to setText() from a thread running, I get an exception above. I looked at many many websites and here too. Found many things, but I really do not understand. Please explain to me in the most simple way or offer me some simple fix if possible.
Thank you very much!!
public class chatter extends Activity {
private String name = "Unknown User";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final EditText msgToServer = (EditText) findViewById(R.id.msgBox);
final EditText chatFromServer = (EditText) findViewById(R.id.chatBox);
final Button MsgToServer = (Button) findViewById(R.id.sendButton);
Socket socket = null;
String ipAddress = "192.168.1.103";
try {
InetAddress serverAddr = InetAddress.getByName(ipAddress);
Socket socketMain = new Socket(serverAddr, 4444);
socket = socketMain;
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("TCP", "error", e);
}
final OutMsg outMsg = new OutMsg(socket);
Thread msgSenderThread = new Thread(outMsg);
msgSenderThread.start();
//chatFromServer.post(new InMsg(socket, chatFromServer));
Thread msgReceiverThread = new Thread(new InMsg(socket, chatFromServer));
msgReceiverThread.start();
MsgToServer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msgToServerString;
msgToServerString = msgToServer.getText().toString();
outMsg.message = name + ": " + msgToServerString;
outMsg.readyToSend = true;
msgToServer.setText("");
}
});
}
public void updateResultsInUi (String msg)
{
final EditText chatFromServer = (EditText) findViewById(R.id.chatBox);
chatFromServer.setText(msg);
}
public class InMsg implements Runnable {
Socket socket;
EditText chatFromServer;
public InMsg(Socket socket, EditText chatFromServer)
{
this.socket = socket;
this.chatFromServer = chatFromServer;
}
public void run(){
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = "FIRSTMESSAGEFROMSERVER";
while (true)
{
if (str.equals("FIRSTMESSAGEFROMSERVER"))
str = in.readLine();
else
str = str + "\n" + in.readLine();
Log.e("TCP", "got the message: " + str);
//Here is where went wrong******************
chatFromServer.setText(str);
//******************************************
}
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("TCP", "error in receiving", e);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.setNameMenu:
setname();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void populateChatBox (String msgFromS)
{
Log.e("TCP", "going in to popC");
final EditText textNameInput = (EditText) findViewById(R.id.nameBox);
Log.e("TCP", " popC");
textNameInput.setText(msgFromS);
Log.e("TCP", "going out from popC");
}
public void setname()
{
setContentView(R.layout.custom_dialog);
final EditText textNameInput = (EditText) findViewById(R.id.nameBox);
Button submitNameButton = (Button) findViewById(R.id.submitNameButton);
submitNameButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String nameinput = textNameInput.getText().toString();
if (!name.equals(""))
name = nameinput;
setContentView(R.layout.main);
}
});
}
}
In your run() method:
Message msg = new Message();
String textTochange = "text";
msg.obj = textTochange;
mHandler.sendMessage(msg);
Create the mHandler in your UI thread;
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String)msg.obj;
//call setText here
}
};
You are not on the UI thread when setting the text. You need to be on UI if you want to work on UI items. Create a message handler on the UI thread, post your messages to it and call setText from the handler on the UI thread.
you can do this whenever you are in a thread:
msgToServer.post(new Runnable() {
public void run() {
msgToServer.setText("your text here");
}
}
Your problem is that there are certain interactions that you can only do on the UI thread. This is one of them.
Looks like you might want to use AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
Basically you could make your Runnable an AsyncTask instead and do the setText in onProgressUpdate, which gets run on the UIThread.
If you would like to use an AsyncTask to run in the background this is how I would do it:
public class UpdateTextProgress_Task extends AsyncTask<Void,String,Void> {
Socket socket;
EditText chatFromServer;
UpdateTextProgress_Task(EditText chatFromServer, Socket socket){
this.socket = socket;
this.chatFromServer = chatFromServer;
}
#Override
protected Void doInBackground(Void... params) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = "FIRSTMESSAGEFROMSERVER";
while(true){
if (str.equals("FIRSTMESSAGEFROMSERVER")){
str = in.readLine();
}
else{
str = str + "\n" + in.readLine();
}
Log.e("TCP", "got the message: " + str);
publishProgress(str); // calls the onProgressUpdate method
}catch (IOException e) {
Log.e("UpdateTextProgress", e.getMessage());
}
return null;
}
#Override
protected void onProgressUpdate(String... progress) {
chatFromServer.setText(progress[0]); //now we are on the UI thread so we can update our EditText
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.e("UpdateTextProgress", "Finished");
}
}
To execute the code:
UpdateTextProgress_Task task = new UpdateTextProgress_Task(chatFromServer,socket);
task.execute();

Categories

Resources