I am developing a serialport application for knx modules in android. I can send and recieve commends to knx modulde.
I want to change ui(for ex. button properties) when a message recieved from serialport. I tried it with handlers but i havent be able to change ui. help me plss.
#Override public void OnSerialsData(final byte[] buffer, final int
size) { .... }
its my serialport listener function calling insine ReadThread. This thread is starting in differend package from my activity. I want to send a message in this method to main activity.
You can use Activity.runOnUiThread() to communicate with UI thread. Read more about Processes and Threads, especially about worker threads.
For example within your OnSerialsData, you can call
mActivity.runOnUiThread(new Runnable() {
public void run() {
mActivity.mButton.setText("message arrived!");
}
}
first you have to create a static handler inside your main activity:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public static Handler myHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.e("Test", msg.getData().getCharSequence("MAINLIST").toString());
}
};
}
then in your socket class:
public void OnSerialsData(final byte[] buffer, final int size) {
Message msg = MainActivity.myHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putCharSequence("MAINLIST", "IS_OK");
msg.setData(bundle);
MainActivity.myHandler.sendMessage(msg);
}
but you have to ensure that your handler must be created before you call OnSerialsData method.
I hope this help.
just extending #auselen answer.
Create on your activity the following:
public void messageReceived(final String msg){
runOnUiThread(new Runnable() {
#Override
public void run() {
// Put here your code to update the UI
}
});
}
and then you can call this from any class that have a reference to your activity.
If the class does not have a reference to the activity, then you should pass the reference to it.
Related
Can I create onClickListener() for a button in more than 1 threads that are executing simultaneously?
Would that listener be called individually in every thread?
No, a button has only one onClickListener. Setting a second one overwrites any listener set previously. And that function will only be called on the UI thread. You can pass messages to multiple threads from that function though.
There are a lot of ways to communicate between threads. Since you are wondering how to pass something over to the thread, here is a simple example:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
...
//Start a thread you need to
anotherThread = new AnotherThread();
anotherThread.start();
}
protected void onResume() {
...
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
anotherThread.sendData(message);
}
});
}
}
public class AnotherThread extends Thread {
//Instantiate handler to associate it with the current thread.
//Handler enqueues all tasks in the MessageQueue using Looper
//and execute them upon coming out of queue;
private Handler handler;
#Override
public void run() {
try {
//Here we create a unique Looper for this thread.
//The main purpose of which to keep thread alive looping through
//MessageQueue and send task to corresponding handler.
Looper.prepare();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//manage incoming messages here
String value = msg.getData().getString("key");
}
};
Looper.loop();
} catch (Throwable e) {
e.printStackTrace();
}
}
public synchronized void sendData(Message message) {
handler.post(new Runnable() {
#Override
public void run() {
handler.sendMessage(message);
}
});
}
}
To get more about thread communication I'd recommend you the following:
1, 2, 3.
I'm writing an app that will display the current download speed which will be updated every second. My Runnable class is able to update the UI with the value, but when I try to place it inside a loop so that it will continuously run and update the UI TextView every second, the app now hangs.
This is my MainActivity.java:
public class MainActivity extends Activity implements SpeedMeter.TaskRunnableSpeedMeterMethods{
private Thread mSpeedMeterThread;
private Handler mHandler;
private TextView downloadSpeedOutput;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadSpeedOutput = (TextView) findViewById(R.id.speed);
mHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message inputMessage) {
SpeedMeter speedMeter = (SpeedMeter) inputMessage.obj;
downloadSpeedOutput.setText(Long.toString(speedMeter.getmDownloadSpeedKB()));
}
};
SpeedMeter speedMeter = new SpeedMeter(this);
speedMeter.run();
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MainActivity.class);
}
#Override
public void setSpeedMeterThread(Thread currentThread) {
mSpeedMeterThread = currentThread;
}
#Override
public void setInternetSpeed(SpeedMeter speedMeter) {
Message completeMessage = mHandler.obtainMessage(1, speedMeter);
completeMessage.sendToTarget();
}
}
And here's the other SpeedMeter.java:
public class SpeedMeter implements Runnable {
final TaskRunnableSpeedMeterMethods mMainActivity;
private long mDownloadSpeedKB;
public SpeedMeter(TaskRunnableSpeedMeterMethods mainActivity) {
mMainActivity = mainActivity;
}
#Override
public void run() {
mMainActivity.setSpeedMeterThread(Thread.currentThread());
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
// while(true) {
long rxBytesPrevious = TrafficStats.getTotalRxBytes();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long rxBytesCurrent = TrafficStats.getTotalRxBytes();
long downloadSpeed = rxBytesCurrent - rxBytesPrevious;
setmDownloadSpeedKB(downloadSpeed/1000);
mMainActivity.setInternetSpeed(this);
// }
}
public long getmDownloadSpeedKB() {
return mDownloadSpeedKB;
}
public void setmDownloadSpeedKB(long mDownloadSpeedKB) {
this.mDownloadSpeedKB = mDownloadSpeedKB;
}
interface TaskRunnableSpeedMeterMethods {
void setSpeedMeterThread(Thread currentThread);
void setInternetSpeed(SpeedMeter speedMeter);
}
}
Any help will be appreciated!
You didnt start your runnable as a new thread instead you called the run function like a normal function (so u do the while loop on ur UI thread which blocks it)
replace
speedMeter.run();<br />
SpeedMeter speedMeter = new SpeedMeter(this);
with
new Thread(new SpeedMeter(this)).start();
see https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html for more infos on how to start a Runnable :)
The ideal way to do this would be to create an AsyncTask that would post a message to your UI thread, after it complete the task in the doInBackground() call.
Standards
also the interface structure you are following does not make sense and does not follow good standards. Usually an interface is used as a callback, which is basically what you are doing. But the standard is to say onSomethingChangedA() or onSomethingChangedB() from OnSomethingChangedListener interface.
I think your loop is always true so app hangs its better to create a boolean and use while(mboolean) and put this in your loop
if(something){
mboolean=false;
}
you can also use CountDownTimer.
for example:
new CountDownTimer(miliseconds,1000)
//if you have download speed and download size you can find miliseconds
#Override
public void onTick(long l) {
//something you want to do every seconds
}
#Override
public void onFinish() {
//something you want to do on finish
}
I am learning how to use Looper and Handler class in android development
http://developer.android.com/reference/android/os/Looper.html
The example given in the android development is not clear to understand what is the usage and the how to use it.I dont know how to add Handler inside the Looper and how I can call the Looper to loop.
If it is available, can anyone give me a simple example to use it.
public class LooperTest extends Activity{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
private class LooperTesting extends Thread
{
public Handler handler;
public void run()
{
Looper.prepare();
handler = new Handler()
{
public void handlerMessage(Message msg)
{
// do something
}
};
Looper.loop();
}
}
}
Hope this Links are helps to u
Link1
Link2
Link3
In your example you have only defined a Thread with a Looper. You need to start the Thread with the associated Looper before you can post any messages to it. I've added some code to your example to illustrate what has to be done:
public class LooperTest extends Activity{
LooperTesting mBgThread;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBgThread = new mBgThread();
// Start the thread. When started, it will wait for incoming messages.
// Use the post* or send* methods of your handler-reference.
mBgThread.start();
}
public void onDestroy() {
// Don't forget to quit the Looper, so that the
// thread can finish.
mBgThread.handler.getLooper().quit();
}
private class LooperTesting extends Thread
{
public Handler handler;
public void run()
{
Looper.prepare();
handler = new Handler()
{
public void handlerMessage(Message msg)
{
// do something
}
};
Looper.loop();
}
}
}
I need a timer which will send a message for its' handler. I've made a class that implements Runnable and I feed its' object to the thread runnable constructor. When I start the thread it hangs application and it obviously isn't working asyncroniously. I could've used AsyncTask but I've also heard that they're designed for short-term operations while my background timer must work throughout activity onResumed state. Would you mind pointing out my mistake and maybe giving useful links on the subject of threads in android. Thanks.
Here's the code I've written:
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
_myTimerInstance = new MyTimer(new Handler() {
#Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
// ...
}
});
_myThread = new Thread(_myTimerInstance);
_myThread.run();
}
private static class MyTimer implements Runnable {
private Handler _myHandler;
private boolean _activityHasBeenLeft;
public MyTimer(Handler myHandler) {
_myHandler = myHandler;
}
public void setActivityHasBeenLeft(boolean b) {
_activityHasBeenLeft = b;
}
#Override
public void run() {
while (!_activityHasBeenLeft) {
try {
Thread.sleep(2000);
_myHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You should always use Thread.start() not Thread.run()
Thread.run() is like a normal method call and is run on the same thread.
use
_myThread.start();
I have the following:-
public class resApp extends MapActivity implements Runnable {
public void run() {
searchImage.setVisibility(View.GONE);
}
}
I also have a background thread that runs before this but that seems to run ok.
When i run the app the run() never gets called.
Can you help?
This code did work about 6 months ago but the device was 2.1.
Thanks
Chris
edit
I had already implemented
private Handler handler;
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.toString().equalsIgnoreCase("1")) {
ad.dismiss();
} else {
pd.dismiss();
}
}
};
as an example and I already have an asynchronous task that runs in the back ground and in 2.1 I could have getters and setters in there. I have now had to pull these out and put them into the run() method as 2.2 doesn't like setting onclicklistener in an async task.
All I need to do is call the run() method on post execute but have tried everything:-
protected void onPostExecute(Object result) {
// Pass the result data back to the main activity
if (dialog != null) {
resApp.this.dialog.dismiss();
}
}
Could I just do:-
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
this.resApp.run();
}
};
You can call the run() method by using Handler.
Handler myHandler = new Handler();
resApp myObj;
And call it by using myHandler.post(myObj);