In my app I have three buttons and when one button is clicked it calls a thread to start thing is i want to be able to input in edittext string in to the threads and the do some work to it then have it returned to the UI Thread where i can display it or put it into an opengl to display an Object. I've read up on Handles and im not sure i fully understand them and maybe if anyone knows a way to make my own handler code. Also I've read up on Async and I dont think it would benifit my app.(personal opion if it would benifit my app let me know) My question is how would i get the info from UI edittext when enter is pressed to the line thread in DrawingUtils class then work is done to it then it comes back to the UI to be ethier displayed or inputed in an openGl program?
Here is MainActivity class:
public class MainActivity extends Activity implements OnClickListener {
EditText cl;
TextView info;
Button enter;
Button line;
Button arc;
Line callLine = new DrawingUtils.Line();
Enter callEnter = new DrawingUtils.Enter();
Arc callArc = new DrawingUtils.Arc();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
info = (TextView) findViewById(R.id.info);
enter = (Button) findViewById(R.id.enter);
line = (Button) findViewById(R.id.line);
arc = (Button) findViewById(R.id.arc);
Handler UIhandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
String string = bundle.getString("myKey");
}
};
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.enter:
callEnter.start();
break;
case R.id.line:
callLine.start();
break;
case R.id.arc:
callArc.start();
break;
}
};
}
Here is DrawingUtils class:
public class DrawingUtils {
MainActivity handle = new MainActivity();
// Thread classes for buttons
public static class Enter extends Thread {
Thread enter = new Thread() {
public void run() {
}
};
public static class Line extends Thread {
Thread line = new Thread() {
public void run() {
}
};
}
public static class Arc extends Thread {
Thread arc = new Thread() {
public void run() {
}
};
}
}
}
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstance) {
// ....
Handler myHandler = new Handler() {
#Override
public void handleMessage (Message msg) {
doCoolStuffWhenMessageReceived();
}
}
MySecondClass secondClass = new MySecondClass(myHandler);
// ....
}
}
public class MySecondClass {
private handler;
public MySecondClass(Handler handler){
this.handler = handler;
}
private void someMethodToCallActivity() {
handler.sendEmptyMessage(0);
}
}
Related
This question already has answers here:
Running code in main thread from another thread
(17 answers)
Closed 5 years ago.
I'm trying to dynamically update an android LinearLayout in the main thread.
Unfortunately I'm having a lot of trouble ascertaining anything from the tutorials online. None of them seem to provide a complete picture of how to communicate between threads.
My idea is something like this:
public class MainActivity extends AppCompatActivity {
private LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
setContentView(layout);
Updater updater = new Updater();
Thread workerThread = new Thread(updater);
//somehow update layout
The updater class would look something like this:
public class Updater implements Runnable {
private int count = 0;
public Updater() {}
#Override
public void run()
{
for (int i = 0; i < 10; i ++){
try {
count++;
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I know I need a Handler in order to communicate messages between the threads, but I don't know how to set that up.
I would like to avoid anonymous classes, and dynamically create new TextViews whenever Updater has a new message.
create WorkerThreadListener interface:
public interface WorkerThreadListener {
void onUpdate(int counter);
}
Change your Updater class:
public class Updater implements Runnable {
private final WorkerThreadListener mWorkerThreadListener;
private final Handler mHandler;
private int count = 0;
public Updater(final WorkerThreadListener workerThreadListener) {
this.mWorkerThreadListener = workerThreadListener;
this.mHandler = new Handler();
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
count++;
mHandler.post(new Runnable() {
#Override
public void run() {
mWorkerThreadListener.onUpdate(count);
}
});
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Change MainActivity class:
public class MainActivity extends AppCompatActivity {
private LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
setContentView(layout);
Updater updater = new Updater(new WorkerThreadListener() {
#Override
public void onUpdate(int counter) {
//update layout here
}
});
Thread workerThread = new Thread(updater);
workerThread.start();
}
}
Hi please check my below answer hope it helps you.
public class ProgressTestActivity extends Activity {
private ProgressBar progress;
private TextView text;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progress = (ProgressBar) findViewById(R.id.progressBar1);
text = (TextView) findViewById(R.id.textView1);
}
public void startProgress(View view) {
// do something long
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
doFakeWork();
progress.post(new Runnable() {
#Override
public void run() {
// here you can add any view or anyof your logic which is related to UI put it into here.
text.setText("Updating");
progress.setProgress(value);
}
});
}
}
};
new Thread(runnable).start();
}
// Simulating something timeconsuming
private void doFakeWork() {
SystemClock.sleep(5000);e.printStackTrace();
}
}
Other ways are also possible.if you have any doubt please comment below post i will explain you in details.
If you just want to use a tick timer and set progress to ui thread . You can use CountDownTimer.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView;
private CountDownTimer countDownTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new);
textView = (TextView) findViewById(R.id.textView);
findViewById(R.id.b2).setOnClickListener(this);
}
public void processData() {
countDownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
textView.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
textView.setText("done!");
}
}.start();
}
#Override
protected void onStop() {
super.onStop();
if (countDownTimer != null) {
countDownTimer.cancel();
}
}
#Override
public void onClick(View v) {
processData();
}
}
Apart from that to post a callback on UI thread you can use Handler .
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
mainThreadHandler.post(new Runnable() {
#Override
public void run() {
}
});
I have a specific scenario and I need your help.
I'm trying to build an App in Android that involves network communication.
I am using AsyncTask for the http POST requests.
I have another class called Proxy (not a good one.. will be changed) which holds different kinds of functionalities (registerUser, setUserName, getUserPermission...)
And Of course, I have an Activity.
My Activity holds an instance of Proxy class.
My goal, is to push a button in the activity, it will call a method from Proxy class, which in its turn calls the AsyncTask's execute() method that actually run the http POST.
I was wondering how to get the data from AsyncTask's onPostExecute to my activity.
What I have in mind is to have an interface in AsyncTask, which will be implemented in Proxy class, and another interface in Proxy class which will be implemented in my Activity class.
Roll the data all the way to my Activity.
I want to hear your thoughts about whether this is the way to go, or another approach is preffered.
Thanks a lot for your help.
Adding some code
public class RegisterActivity extends FragmentActivity implements Proxy.OnProxyHttpPostResponseListener {
private Proxy proxy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
this.proxy = new Proxy();
this.proxy.setHttpPostResponseListener(this);
}
#Override
public void onProxyHttpPostResponse(String response) {
//Do something when http post returns
}
}
public class Proxy {
public interface OnProxyHttpPostResponseListener {
void onProxyHttpPostResponse(String response);
}
private OnProxyHttpPostResponseListener httpPostResponseListener;
public void setHttpPostResponseListener(OnProxyHttpPostResponseListener listener) {
this.httpPostResponseListener = listener;
}
private class HttpPostAsync extends AsyncTask<Pair<String, ArrayList<Pair<String, String>>>, Void, String> {
#Override
protected String doInBackground(Pair<String, ArrayList<Pair<String, String>>>... params) {
return this.httpPost(params[0].first, params[0].second);
}
protected void onPostExecute(String response) {
httpPostResponseListener.onProxyHttpPostResponse(response);
}
}
If you're just needing HTTP POST functionality then an AsyncTask might not be the best choice. AsyncTask really shines if you need to get progress updates as the task is executing (with onProgressUpdate(Progress... progress)). If you'd like to use AsyncTask nonetheless, iroiroys' reply should help.
A bit more simply, you could just use a Handler thread straight up. Something like this:
public class HandlerExampleActivity extends Activity {
private Button postButton;
private Button getButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_example);
backgroundThread = new BackgroundThread();
backgroundThread.start();
postButton = (Button) findViewById(R.id.button_post);
postbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
backgroundThread.post("DATA_HERE");
}
});
getButton = (Button) findViewById(R.id.button_get);
getbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
backgroundThread.get("URL_HERE");
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
backgroundThread.exit();
}
private class BackgroundThread extends Thread {
private Handler backgroundHandler;
public void run() {
Looper.prepare();
backgroundHandler = new Handler();
Looper.loop();
}
public void post(DataType data) {
backgroundHandler.post(new Runnable() {
#Override
public void run() {
// pull data and do the POST
uiMsg = uiHandler.obtainMessage(POST_COMPLETE, whatever_data_passing_back, 0, null);
uiHandler.sendMessage(uiMsg);
}
});
}
public void get(URL data) {
backgroundHandler.post(new Runnable() {
#Override
public void run() {
// GET data
uiMsg = uiHandler.obtainMessage(GET_COMPLETE, whatever_data_passing_back, 0, null);
uiHandler.sendMessage(uiMsg);
}
});
}
public void exit() {
backgroundHandler.getLooper().quit();
}
}
private final Handler uiHandler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what) {
case POST_COMPLETE:
// handle it
break;
case GET_COMPLETE:
// handle it
break
case MESSAGE_BACK_TO_UI_THREAD:
// do something
break;
case OPERATION_FAIL:
// oh no!
break;
case OPERATION_SUCCESS:
// yay!
break;
}
}
};
}
I suggest you try Handler and Handler.Callback.
Below I made it simple example..
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
public class MainActivity extends Activity implements Callback {
Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler(this);
Proxy proxy = new Proxy(handler);
proxy.foo();
}
private class Proxy {
Handler handler;
public Proxy(Handler handler) {
this.handler = handler;
}
private void foo() {
new myAsync().execute();
}
private class myAsync extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Message msg = handler.obtainMessage();
msg.obj = result;
handler.sendMessage(msg);
}
}
}
#Override
public boolean handleMessage(Message msg) {
// Handle Message here!
return false;
}
}
I am having a strange issue playing a VideoView. I have done my best to simplify the code as much as possible. Below are 4 classes: A, MirrorActivity, Replay, and MyTask. Assume the following occurs in this order:
A is created.
MirrorActivity() is created.
Inside MirrorActivity()'s onCreate(), that instance calls A's setMirrorActivity() to allow A to have a reference to it.
A's doThis() method is called, which executes mirrorActivity.playVideo().
playVideo() is executed.
Replay's executeVideo() is called.
MyTask is executed.
For some strange reason, when the above is executed, the video does not play. However, when the myButton ImageButton is pressed inside MirrorActivity, it plays the video on command. Both of these seem to be doing the same thing by calling MirrorActivity's playVideo(). Do you know why the above does not execute?
A
public class A{
private static final A instance = new A();
private MirrorActivity mirrorActivity;
public static A getInstance() {
return instance;
}
public void setMirrorActivity(MirrorActivity mirrorActivity) {
this.mirrorActivity = mirrorActivity;
}
public void doThis(String url){
mirrorActivity.playVideo(String url);
}
}
MirrorActivity
public class MirrorActivity extends Activity {
public static String VIDEO_URL = "example.mp4";
public VideoView mVideoView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overlay_gradient);
// Set Mirror Activity
A.getInstance().setMirrorActivity(this);
mVideoView = (VideoView) findViewById(R.id.mirrorVideoView);
MyTask vTask = new MyTask(mVideoView);
ImageButton myButton = (ImageButton) findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v)
{
MirrorActivity.this.playVideo(MirrorActivity.VIDEO_URL);
}
});
}
public void playVideo(String videoURL)
{
MyTask mt = new MyTask(mVideoView);
Replay.executeVideo(MirrorActivity.VIDEO_URL,
this,
mVideoView,
mt);
}
}
Replay
public class Replay{
public static void executeVideo(String uri, Activity activity, VideoView vid, MyTask mt)
{
vid.setMediaController(new MediaController(activity););
vid.setVideoURI(Uri.parse(uri));
mt.execute();
}
}
MyTask
public class MyTask extends AsyncTask<Void, Integer, Void> {
private VideoView video;
private int duration = 0; // in milliseconds
public MyTask(VideoView vid) {
video = vid;
}
#Override
protected Void doInBackground(Void... params) {
video.start();
video.requestFocus();
video.setOnPreparedListener(new OnPreparedListener(){
#Override
public void onPrepared(MediaPlayer mp) {
duration = video.getDuration();
}
});
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}
I think UI element cannot access in doInBackground . And also start() after every declaration.
Try this method too.
private MediaController ctlr;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_overlay_gradient);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
// Set Mirror Activity
A.getInstance().setMirrorActivity(this);
mVideoView = (VideoView) findViewById(R.id.mirrorVideoView);
Uri uri=Uri.parse(videourl or video path);
mVideoView .setVideoURI(uri);
mVideoView .setVideoPath(videourl);
ctlr=new MediaController(this);
ctlr.setAnchorView(video);
ctlr.setMediaPlayer(video);
mVideoView .setMediaController(ctlr);
mVideoView .requestFocus();
mVideoView .start();
}
Omg. I believe I found the solution. I'm sorry to those who were investigating, but here is what I did to get it to work both ways. Pressing imageButton and calling A.doThis() will be able to play the video now.
I modified MirrorActivity's playVideo() function to use the following:
public void playVideo(final String videoURL)
{
Runnable runnable = new Runnable(){
#Override
public void run()
{
MyTask mt = new MyTask(mVideoView);
Replay.executeVideo(videoURL,
MirrorActivity.this,
mVideoView,
mt);
}
});
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(runnable);
}
Like the title suggest I have an android project with a MainActivity class that has a TextView that I want to set the text of after receiving a message. I also have a class that runs a ServerSocket on a separate thread that receives the string message I want to display.
Part of my MainActivity looks like this,
private Handler UIHandler = new Handler();
private RemoteControlServer remoteConnection;
public static final int controlPort = 9090;
public class MainActivity extends Activity implements SensorEventListener
{
...
remoteConnection = new RemoteControlServer(controlPort, UIHandler);
...
private class RemoteControlServer extends RemoteControl
{
RemoteControlServer(int port, Handler ui)
{
super(port, ui);
}
#Override
public void onReceive(String[] msg)
{
//updates messages textview
}
#Override
public void onNotify(String[] msg)
{
//updates notification textview
}
}
}
The RemoteControlServer implementation of code that calls the onReceive(String[] msg) and also handles receiving messages on the different thread looks like this,
...
public abstract void onReceive(String[] msg);
public abstract void onNotify(String[] msg);
...
controlListener = new Thread(new Runnable()
{
boolean running = true;
public void run()
{
String line = null;
while(running)
{
try
{
//Handle incoming messages
...
onReceive(messages);
}
catch (final Exception e)
{
UIHandler.post(new Runnable()
{
public void run()
{
onNotify("Wifi Receive Failed " + e.toString() + "\n");
}
});
}
}
}
});
...
I'm getting the error "Only the original thread that created a view hierarchy can touch its views." when onReceive() is called and throws the exception and calls onNotify() with the exception description. Why does the onNotify() work but the otherone does not? How can I correctly call the listener to the the TextView and update its text? Thanks
private class RemoteControlServer extends RemoteControl
{
...
public class BridgeThread implements Runnable
{
String[] msgArray = null;
public BridgeThread(String[] msg)
{
msgArray = msg;
}
public void run()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
TextView zValue = (TextView) findViewById(R.id.connectionStatus);
zValue.setText(msgArray[0]);
}
});
}
}
#Override
public void onReceive(String[] msg)
{
BridgeThread bridgeTest = new BridgeThread(msg);
bridgeTest.run();
}
...
}
I'm trying to send data to my Thread called ToD1 which is in an inner class of my Threads class then I need to do some work to it then need it to be set back to the UI thread handler my qestion is how would I call the Handlers to send the Message data? I know about AsyncTask and will try using it later the purpose of this app is for me to learn and understand the concepts of Handlers, HandlerThread, and AsyncTask so I can use them in my programing.
Here is my code for MainActivity:
public class MainActivity extends Activity implements OnClickListener {
TextView display1;
TextView display2;
EditText cl;
Button enter;
Button tod1;
Button tod2;
Bundle d = new Bundle();
static Handler mHandler;
Message msg;
Object task;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tod1 = (Button) findViewById(R.id.display1);
tod2 = (Button) findViewById(R.id.display2);
enter = (Button) findViewById(R.id.Enter);
display1 = (TextView) findViewById(R.id.Display1);
display2 = (TextView) findViewById(R.id.Display2);
cl = (EditText) findViewById(R.id.CL);
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.Enter:
Bundle in = new Bundle();
String input = cl.getText().toString();
d.putString("in", input);
msg.setData(d);
// eclipes ask to resovle d1 varible type?
d1.sendMessage(msg);
notifyAll();
break;
case R.id.display1:
break;
case R.id.display2:
break;
}
}
}
Here is my Thread class:
public class Threads {
public static class ToD1 {
Thread display1 = new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
Message msg = new Message();
Bundle b = new Bundle();
Looper.prepare();
Handler d1 = new Handler() {
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
};
String output;
b.putString("key1", "out:" + String.valueOf(output));
msg.setData(b);
// Send msg to UI thread handler
// eclipes asked solve mHandler to varible type
mHandler.sendMessage(msg);
}
};
}
}