I am trying the following scenario
1)send a message from UI thread , to worker using HandlerThread
2)Read it using handlemessage
3)send it back to a text field in UI
I am using the below code , The issue now is that , the message in the handlemessage is coming as null
public class MainActivity extends AppCompatActivity {
private TextView serverStatus;
private TextView clientStatus;
private Handler mUiHandler = new Handler();
private BluetoothServerSocket serverSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button readButton = (Button) findViewById(R.id.button2);
readButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//TODO Code to manage read data from client here !!
/* mWorkerThread2 = new MyWorkerThread("myWorkerThread2");
mWorkerThread2.start();
*/
}});
final Button submitButton = (Button) findViewById(R.id.button);
serverStatus=(TextView) findViewById(R.id.editText);
submitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
HandlerThread myThread = new HandlerThread("Worker Thread");
myThread.start();
Looper mLooper = myThread.getLooper();
MyHandler mHandler = new MyHandler(mLooper);
/* Bundle data = new Bundle();
data.put
msg.setData(data);*/
Message msg = mHandler.obtainMessage();
msg.obj = serverStatus.getText().toString();// Some Arbitrary object
/* Toast.makeText(getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show();*/
mHandler.sendMessage(msg);
}});
}
class MyHandler extends Handler {
public MyHandler(Looper myLooper) {
super(myLooper);
}
public void handleMessage(final Message msg) {
//final String text=msg.getData().getString("");
mUiHandler.post(new Runnable() {
#Override
public void run() {
String ms=String.valueOf(msg.obj);
serverStatus.setText("from server !!! "+ms );
}
});
}
}
}
As per comments from #pskink , I have used CallBack . Below code works fine
public class MainActivity extends AppCompatActivity {
private TextView serverStatus;
private TextView clientStatus;
private Handler mUiHandler = new Handler();
Handler mHtHandler;
// Handler mUiHandler;
private BluetoothServerSocket serverSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button readButton = (Button) findViewById(R.id.button2);
readButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//TODO Code to manage read data from client here !!
}});
final Button submitButton = (Button) findViewById(R.id.button);
serverStatus=(TextView) findViewById(R.id.editText);
submitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
HandlerThread ht = new HandlerThread("MySuperAwsomeHandlerThread");
ht.start();
Handler.Callback callback = new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == 0) {
final Message msg1=mUiHandler.obtainMessage(0);
msg1.obj=msg.obj;
mUiHandler.post(new Runnable() {
#Override
public void run() {
final String ms=(String)msg1.obj;
serverStatus.setText("from server !!! "+ms );
}
});
}
return false;
}
};
mHtHandler = new Handler(ht.getLooper(), callback);
Message msg=mHtHandler.obtainMessage(0);
msg.obj = serverStatus.getText().toString();// Some Arbitrary object
mHtHandler.sendMessage(msg);
}});
}
}
Related
I've a horizontal progressbar which shows progress from 0 to 100. What I want is to restart the progressbar again from 0 when it reaches 100. I'll be showing this in a Fragmentdialog. For now I'm checking it in activity itself. How to do that?
public class MainActivity extends AppCompatActivity{
private Button startbtn, stopbtn;
ProgressBar pb;
private TextView progressTxt;
int progressBarValue = 0;
Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = new CShowProgress(MainActivity.this);
btn = (Button)findViewById(R.id.btn);
startbtn = (Button)findViewById(R.id.startbtn);
stopbtn = (Button)findViewById(R.id.stopbtn);
pb = (ProgressBar)findViewById(R.id.progressBar);
progressTxt = (TextView)findViewById(R.id.progressTxt);
startbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myprogress(true);
}
});
stopbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myprogress(false);
}
});
}
private void myprogress(final Boolean isStart){
handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
if(isStart && progressBarValue<100)
{
progressBarValue+=1;
pb.setProgress(progressBarValue);
progressTxt.setText(String.valueOf(progressBarValue));
handler.sendEmptyMessageDelayed(0, 100);
}
}
};
handler.sendEmptyMessage(0);
}
}
I assume this chunk of code will work for your use case:
private void myprogress(final Boolean isStart) {
handler = new Handler() {
public void handleMessage(Message msg) {
if (isStart && progressBarValue < 100) {
...
} else if (isStart) {
// progressBarValue is equal to 100
// make it zero and do the same thing again
progressBarValue = 0;
progressBarValue += 1;
pb.setProgress(progressBarValue);
progressTxt.setText(String.valueOf(progressBarValue));
handler.sendEmptyMessageDelayed(0, 100);
}
}
};
handler.sendEmptyMessage(0);
}
First, you should use a counter mechanizm (run a delayed handler, timer, thread or something else)to check current progress periodically.
(progressTxt.getProgress == 100)
will do the trick.
Another way is using this answer.
I have one class in which a listener is implemented and depending on the methods call in listener, I am to update the data in corresponding activities. For this, i am interested in using the different-different handlers for each activity.
Since, my handler class in each activity is static and hence, handler object is non-static in activity.
So, problem is how to use those activity's handlers to send Message to them.? Help?
This is one of my class in which I am to update the data from another class: How to do?
public class HandlerActivity extends Activity {
TextView tv;
int counter;
Handler handler = new HandlerExtension(this);
//handler static class
private static class HandlerExtension extends Handler {
private final WeakReference<HandlerActivity> targetActivity;
//constructor
HandlerExtension(HandlerActivity activity){
this.targetActivity = new WeakReference<HandlerActivity>(activity);
}
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerActivity activity = targetActivity.get();
if(activity != null){
final String data = msg.getData().getString("counter");//gettting msg data
activity.tv.setText(data);
}
}
}//HandlerExtension
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handler_activity);
Button startB = (Button) findViewById(R.id.button1);
tv = (TextView) findViewById(R.id.textView1);
final Runnable runnable = new Runnable() {//object to be executed in the thread
#Override
public void run() {
counter+=10;
String result = String.valueOf(counter);
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("counter", result);
msg.setData(bundle);
handler.sendMessage(msg);//Now, updating the view from background thread via handler
SystemClock.sleep(1000);
}
};
//starting the background thread on button click
startB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(runnable).start();
}
});
}//onCreate
}//HandlerActivity
getting CalledFromWrongThreadException, Only the original thread that created a view hierarchy can touch its views.
on the line, handler2.sendMessage(msg); which is for sending a short text message from the UI thread to MulitThreaderSendback class below.
calling the sendMessage(msg) works perfectly when calling it from inside of the onCreate method, however when i put it inside of the onClick listener it is causing this exception crash.
how can I avoid this crash and be able to call it from an onclick listener so I can use a button press to send the message?
FROM LOGCAT:
E/AndroidRuntime(14366): FATAL EXCEPTION: Thread-1433
E/AndroidRuntime(14366): android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
E/AndroidRuntime(14366): android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5432)
E/AndroidRuntime(14366): android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:970)
Code is:
public class MainActivity extends Activity implements Runnable {
TextView textViewOne;
TextView textViewTwo;
TextView textViewThree;
TextView textViewFour;
TextView textViewFive;
RelativeLayout relativeLayoutOne;
Handler handler;
Handler handler2;
Message msg;
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
relativeLayoutOne = (RelativeLayout) findViewById(R.id.relativeLayout1);
textViewOne = (TextView) findViewById(R.id.textView1);
textViewTwo = (TextView) findViewById(R.id.textView2);
textViewThree = (TextView) findViewById(R.id.textView3);
textViewFour = (TextView) findViewById(R.id.textView4);
textViewFour = (TextView) findViewById(R.id.textView5);
handler = new Handler();
// starting this class that implements Runnable
this.run();
// starting class that extends Thread
MultiThreader multiThreader = new MultiThreader(handler);
multiThreader.start();
// starting class that implements Runnable
MultiThreader2 multiThreader2 = new MultiThreader2(handler);
Thread thread = new Thread(multiThreader2);
thread.start();
MulitThreaderSendback multiSendBack = new MulitThreaderSendback();
Thread thread2 = new Thread(multiSendBack);
thread2.start();
synchronized (multiSendBack) {
while (handler2 == null) {
try {
multiSendBack.wait();
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
Bundle bundle = new Bundle();
String messageToSend = "message from UI class";
bundle.putString("message", messageToSend);
Random random = new Random();
int messageText = random.nextInt(30);
String putIt = String.valueOf(messageText);
bundle.putString("message", putIt);
msg = Message.obtain();
msg.setData(bundle);
// handler2.sendMessage(msg); // <-- WORKS OK HERE, NO CRASH
relativeLayoutOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
handler2.sendMessage(msg); // <-- FATAL ERROR: CalledFromWrongThreadException
}
});
} // end oncreate
public void setTextViewThree(String textToSet) {
textViewFour.setText(textToSet);
}
public void setTextViewFour(String textToSet) {
textViewFive.setText(textToSet);
}
// local class runnable
#Override
public void run() {
textViewOne.setText("message from local class runnable");
}
// multiThreader inner class
class MultiThreader extends Thread {
Handler handler;
public MultiThreader(Handler handler) {
this.handler = handler;
}
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
textViewTwo.setText("message from multithreader class");
} // end inner run
});
} // end outer run
} // end MultiThreader inner class
// external multiThreader2 inner class
class MultiThreader2 implements Runnable {
Handler handler;
public MultiThreader2(Handler handler) {
this.handler = handler;
}
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
textViewThree.setText("message from MultiThreader2 class");
} // end inner run
});
} // end outer run
} // end MultiThreader2 inner class
class MulitThreaderSendback implements Runnable {
int x = 0;
#Override
public void run() {
// TODO Auto-generated method stub
Looper.prepare();
synchronized(this) {
handler2 = new Handler() {
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
String receivedString = bundle.getString("message");
setTextViewThree("string received from UI thread: " + receivedString);
}
};
notifyAll();
}
Looper.loop();
} // end run method
} // end MultiThreaderSendback inner class
} // end outer class mainactivity
You can embed the line handler2.sendMessage(msg); in this method
runOnUiThread(new Runnable() {
public void run() {
}
});
Try this
i have a quiz game for my android that has a time limit. what i want is there is a choices button that if you click one of the buttons it you will be automatically intent to the class next level but if you didnt answer or click any of the button you will be intent to the other class, thats why the game has a time limit. my problem is i dont know how to put a time limit that will intent or transfer you in another class automatically if you didnt click any of the button choices. i tried sleep but what happen is even i already clicked the correct answer and im on the next level class it will sleep to the class i intented to my sleep. please help me with my problem. i also try handler but didnt work
public class EasyOne extends Activity {
Button a, b, c;
TextView timer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.easyone);
a = (Button) findViewById(R.id.btn_ea1);
b = (Button) findViewById(R.id.btn_eb1);
c = (Button) findViewById(R.id.btn_ec1);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"CORRECT!",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getApplicationContext(),EasyTwo.class);
startActivity(intent);
}
});
}
private Runnable task = new Runnable() {
public void run() {
Handler handler = new Handler();
handler.postDelayed(task, 5000);
Intent intent = new Intent(getApplicationContext(),TimesUp.class);
startActivity(intent);
}
};
You should use a handler but in order to cancel the timeout you must remove the delayed message from the handler in your click listener code.
public class EasyOne extends Activity {
static private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 123) {
((EasyOne) msg.obj).onTimeout();
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.easyone);
a = (Button) findViewById(R.id.btn_ea1);
b = (Button) findViewById(R.id.btn_eb1);
c = (Button) findViewById(R.id.btn_ec1);
Message msg = mHandler.obtainMessage(123,this);
mHandler.sendMessageDelayed(msg,5000);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"CORRECT!",
Toast.LENGTH_SHORT).show();
mHandler.removeMessages(123,this);
Intent intent = new Intent(getApplicationContext(),EasyTwo.class);
startActivity(intent);
}
});
}
private void onTimeout() {
//your code
}
}
public class Talk extends Activity {
private ProgressDialog progDialog;
int typeBar;
TextView text1;
EditText edit;
Button respond;
private String name;
private String textAtView;
private String savedName;
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.dorothydialog);
text1 = (TextView)findViewById(R.id.dialog);
edit = (EditText)findViewById(R.id.repsond);
respond = (Button)findViewById(R.id.button01);
respond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
text1.setText("Welcome! Enter your name!");
respond.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
name = edit.getText().toString();
text1.setText("Cool! your name is "+name);
}
});
}
});
}
}
Okay so i want to figure out how i would save the state of this activity. this is just a small snippet from my code to show you guys an example. So i want to save the state so when the activity is destroyed the user will come back where they left off.
Second thing, I would like to show a quick 5 second Progress dialog spinner between each button click.
For the second thing
This should work:
public class TestActivity extends Activity implements Runnable, OnClickListener {
private TextView tv;
private ProgressDialog pd;
private Button btn;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
tv = (TextView) this.findViewById(R.id.tv);
btn = (Button)findViewById(R.id.btn);
tv.setText("initial text");
btn.setOnClickListener(this);
}
public void onClick(View v) {
pd = ProgressDialog.show(TestActivity.this, "Please wait...", "Details here", true, false);
Thread thread = new Thread(TestActivity.this);
thread.start();
}
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
tv.setText("text after 5 sec passed");
}
};
}