I'm new to Android. In my current project I'm using the asmack library to receive XMPP messages. In my MainActivity I have:
Connection connection; // from the asmack library
and
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
// HERE! is where I want to update the UI when I receive packets
}
}
The weird thing is when I parse the packet and simply call setText() on two labels. At first nothing happens, but when I touch a Button (hence calling some update routine) only the first label is updated.
Now, as far as I understood you're supposed to use AsyncTask in such cases but this didn't work out either.
Did I misunderstood some core concept? Can someone lead me to the right path?
The packet seems to be processed on a separate thread than the UI thread, which means the UI will not be updated immediately since you're not manipulating it on its thread. Therefore, you should do something like this...
connection.addPacketListener(new PacketListener(){
public void processPacket(Packet packet){
//update the UI on its thread
runOnUiThread(new Runnable()){
public void run(){
//update UI elements
}
}
}
}
Related
I am coding a client-server app to test communication between two Android Bluetooth devices. On my client, I am reading data from the inputstream object.
When I checked by printing on the logcat, the data is being read successfully. However when I try to set the data to a TextView, it is not displaying.
In the following code, packetsReceivedTV is the TextView object. I am getting correct output when I print 'result' on logcat, but the text is not setting in the TextView. Is it because I am setting the text in a while (listening) loop?
while(listening){
bytesRead =instream.read(buffer);
if(bytesRead!=-1){
String dataRead= new String(buffer,"UTF-8");
System.err.println("*************result : "+dataRead);
packetsReceivedTV.setText("Received : "+dataRead);
packetsReceivedTV.invalidate();
}
}
Even a call to invalidate() is not working.
NOTE: Occasionally when I kill the server process on one device, then the TextView on the client device updates correctly. But this does not happen always. Please help!
It's not clear which thread your code is called on, but you need to make sure these two operations are happening on different threads:
The stream polling needs to be done on a background thread. If you are not doing this, then you are not seeing text because the thread blocking on read() keeps the main thread from updating the UI elements.
The setText() method call must happen on the main (UI) thread. If you are not doing this, the text will also not display--and on some devices you will even see crashes.
I'll assume this code live in an activity (since you are trying to update UI elements). While this is not the best practice, a simple example that demonstrates the concept follows:
Thread pollingThread = new Thread() {
#Override
public void run() {
…
//This code needs to be running on a background thread
while(listening){
bytesRead = instream.read(buffer);
if(bytesRead != -1){
String dataRead= new String(buffer,"UTF-8");
System.err.println("*************result : "+dataRead);
runOnUiThread(new Runnable() {
#Override
public void run() {
//This code needs to be posted back to the main thread.
packetsReceivedTV.setText("Received : "+dataRead);
}
});
}
}
}
};
//Start the listener thread
pollingThread.start();
This is really just meant to illustrate the basic point that the polling code must be in the background and the view code must be on the main thread.
Even a call to invalidate() is not working.
TextView calls this internally when its contents change, so you calling it is redundant.
My team is building an Android application that will use websockets to communicate with an existing backend. We chose to use the AndroidAsync by Koushik Dutta to handle this communication.
I would like to register a ping to be sent periodically, to check if the connection is still alive. I'm using Wireshark to check the network traffic. This is a screenshot of the result that Wireshark is showing:
From what I see here, I believe that the ping is being sent, and the pong is being received.
A snippet of my code is:
private void keepAlive() {
ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run() {
Log.d(TAG, "Pinging...");
WebSocketHandler.this.webSocket.ping("LALALA");
}
};
pingScheduledFuture = scheduler.scheduleAtFixedRate(runnable, 0, PING_PERIOD,
TimeUnit.SECONDS);
}
The onPongReceived method just prints into Logcat
#Override
public void onPongReceived(String s) {
// TODO here I'm aware if connection is still alive
Log.d(TAG, "Pong received! " + s);
}
However, Pong received! is never printed! Also, if I put a breakpoint there, the app will never stop executing at that point
Anyone has any idea on what may I be missing here?
Best regards and thanks in advance
I'm not familiar with AsyncSocket but a quick google revealed that you have to register a callback setPongCallback() somewhere for your pong to be received. Are you doing this? You're not showing a lot of code.
The problem was extremely lame, but here's the solution. I forgot to set the callback to the websocket, like this:
WebSocketHandler.this.webSocket.setPongCallback(WebSocketHandler.this);
And then, the pongs were correctly received.
This is my first Android application and I am finding troubles with while loop, I am trying to use a while loop on my Android application but the application freezes.
What I'm trying to do is track the user location (using onlocationChanged) and keep querying on the location until the query returns a result. It's a GIS application so I am going to describe the application behavior:
the application keeps tracking the user position using a listener "onLocationChangedListener" and store it in a variable "myPosition". I am using a boolean"noResults=true". I will use a method "query(myPosition)" in the while loop, this method has a callback that when a result is found, and changes a boolean "noResults" to false. the loop will keep on until "noResults" is false (that means query's callback changed the boolean's value)
, here's what I did:
while(noResults)
{
//myPosition keeps changing
query(myPosition);
//query has a callback that when a result is found it changes noResults to false
}
I resolved the problem using a "Handler" that query the Feature Layer every 5 seconds, this stops the main thread from generating application not responding error:
Handler m_handler=new Handler();
Runnable m_runnable;
m_runnable = new Runnable(){
public void run() {
//query code here
m_handler.postDelayed(m_runnable, 5000);
}
};
m_handler.postDelayed(m_runnable, 0);
running while loop codes on the main thread freezes the UI, and makes all other processes pause making your app unresponsive use
Threads..
also note that the while loop you are running is running on a default Thread termed as the ui thread so in short run while loops on separate threads..
eg..
new Thread(new Runnable() {
#Override
public void run() {
// Your hard while loop here
//get whatever you want and update your ui with ui communication methods.
}
).start();
for ui communicating methods
View.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), "updated ui", Toast.LENGTH_LONG).show();
}
});
the view could be any views you are updating..
also like #TehCoder said you could use asynctask but asynctask is not meant for long workaflow work there are 3 of them but i can't recall the last one
Maybe you should use an AsyncTask? I'm not quite sure what your problem is tho.
Loop is not a problem in android (or any language).
There are two scenario might be reason for your freezing,
If you run network call in api, android throw error and crashes. You have to do network related calls in Aysnc Task ot threading
Use try throw catch and exception cases to avoid app crashing and better coding skill.
I've been developing a few basic Android apps recently and notice a slightly odd behaviour which I'm sure is my own wrong doing.
The problem seems to lie with the main thread which I'm using for both updating the UI and some processing such as sending a message via Bluetooth.
Let's say I have the following:
public void sendMessage(){
updateUI();
sendBtMessage();
}
public void updateUI(){
txtView.setText("Sending message");
progressbar.setVisibility(View.VISIBLE);
}
public void sendBTmessage(){
... connect to BT and send message here
}
As I run my code it appears to be running sendBtMessage first as the UI update appears after the message is sent(I would like it before sending the message). Is this because the main threads priority is to do the heaviest work-load first?
Should the main thread be used for only updating the UI?
Any Suggestions or advice would be appreciated.
Turns out I needed to handle the sendBTMessage on a new thread such as:
new Thread(new Runnable() {
public void run(){
...processing
}
}).start();
and the UI runs smoothly using
RunOnUiThread(Runnable)
I try to write a little game using android and have some problems with threading.
The mainloop of the game runs in this own thread and basically just does something like this:
public void run() {
while (true) {
NativeGameLib.gameTick(t);
}
}
Now I want to pass touch inputs to my NativeGameLib. I thought I use the onTouchEvent() of the view in the UI-thread, create a runable inside and let it execute on the main-loop thread.
But I don't really get how to do it. I have seen that there is a Handler and a Looper class and that I can use the handler to post runables to the messageQueue and the Looper.loop() function to process the queue.
As far as I understand it, the loop() function endlessly checks for new messages and therefore blocks the thread.
So, how can I combine it with my thread. I want to do something like this in the thread:
public void run() {
while (true) {
processMessageQueue();
NativeGameLib.gameTick(t);
}
}
Any ideas?
Thanks.
Did you check View.Post API ?
http://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)