Showing ok cancel Dialogbox through thread - java

I have an Android service which spawns a thread.This thread waits for network data and after receiving that data I want to show Ok Cancel Dialogbox.
I was getting exception can't create handle that should have Looper.prepare().I added Looper.prepare() and Looper.loop() then now I am not getting any exception but its waiting infinitely.

Instead of using a sole thread it's better to use an AsyncTask which is also a speacialized thread for Android.
You can wait for data in the AsyncTask's doInBackGround method and when you received data you can call publishProgress() which will invoke onProgressUpdate method of AsyncTask.
At onProgressUpdate you can update the UI without blocking the main thread and also this is the preferred way of doing long time operations in background like network listening etc.
Check AsyncTask for more info and how to use it.
http://developer.android.com/reference/android/os/AsyncTask.html

You can invoke the UI thread(showing alert dialog) in non-UI thread by using handlers as like below code
new Thread(new Runnable()
{ public void run()
{
try {
///do your stuff in
mHandlerShowDialog.post(mUpdateShowDialog);
///do your struff
}
} ).start();
final Handler mHandlerShowDialog= new Handler();
final Runnable mUpdateShowDialog = new Runnable() {
public void run() {
// show your dialog here
}
};

Related

Animators may only be run on Looper threads Android

I'm trying to animate something when a task is completed. The problem here is I get this error message:
android.util.AndroidRuntimeException: Animators may only be run on Looper threads
at android.animation.ValueAnimator.cancel(ValueAnimator.java:1004)
at android.view.ViewPropertyAnimator.animatePropertyBy(ViewPropertyAnimator.java:965)
at android.view.ViewPropertyAnimator.animateProperty(ViewPropertyAnimator.java:921)
at android.view.ViewPropertyAnimator.alpha(ViewPropertyAnimator.java:735)
at com.design.zaton.prototypei.MainActivity$1$1.run(MainActivity.java:93)
at java.lang.Thread.run(Thread.java:761)
The app worked fine before with the same exact code but now it simply doesn't. I'm really confused.
Here's where the error happens:
new Thread(new Runnable() {
#Override
public void run() {
final String s = getGiphyViews(String.valueOf(mEdit.getText()));
runOnUiThread(new Runnable() {
#Override
public void run() {
result.setText(s);
}
});
loading.animate()
.alpha(0)
.setDuration(100);
done.animate()
.scaleY(1)
.scaleX(1)
.setDuration(300);
}
}).start();
The error outlines the loading.animate() method.
Thanks in advance!
runOnUiThread(new Runnable() {
#Override
public void run() {
//Your code
}
});
You have to execute the code in the UI Thread
Looper threads are threads in Android that permanently loop (or until you cancel them). They work in conjunction with Handlers which will post and send messages to Looper threads. Animators use heavy use of Looper threads because they perform their actions in repeated cycles. This allows the animator to not block after you press "start" so you can continue to perform other actions.
To further complicate matters, you most likely are performing animations on View objects. These can only be run on the main UI thread (which happens to be the biggest Looper thread of them all). So, you can not run these animations on separate threads like you are trying.
I think, there has been a solution for this using Handler. You can use postDelayed to minimal as 100 and run your animating tasks. In your case it would be:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
final String s = getGiphyViews(String.valueOf(mEdit.getText()));
runOnUiThread(new Runnable() {
#Override
public void run() {
result.setText(s);
}
});
loading.animate()
.alpha(0)
.setDuration(100);
done.animate()
.scaleY(1)
.scaleX(1)
.setDuration(300);
}
}, 100);
I had this problem today and above work resolved the problem. I would love to hear from anyone if there is any problem with this method.
Kotlin
If you still want to use a delay (or not)
Handler(Looper.getMainLooper()).postDelayed({
// Your Code
}, 1000)
Put Code Where Are getting error and doing any network operations
new Handler().post(new Runnable() {
#Override
public void run() {
// add your code here
}
});
I think you can create a main handler instance in your activity and override handle message method. you can save a handler quote in your work thread.When you finished work you can use handler to send a message and you receive message in handle message method. To start animation from handler message method and so on...

How do you call a method on the UIThread from a Thread?

While it is useful to run long standing tasks on their own thread running code in the UIThread is necessary in order to update the UI components. Otherwise your application will throw the CalledFromWrongThreadException during execution. How can you run code on the UIThread?
There are a number of ways this can be achieved:
Use runOnUiThread() method call
Use post() method call
Use the Handler framework
Use a Broadcasts and BroadcastReceiver (optionally with LocalBroadcastManager)
Use an AsyncTask's onProgressUpdate() method
Method 1:
runOnUiThread(new Runnable() {
#Override
public void run() {
// do something
}
});
Read more: http://www.intertech.com/Blog/android-non-ui-to-ui-thread-communications-part-1-of-5/#ixzz3hnx3hdS5
Yes you can use handler to communicate between Worker Thread and UI Thread, put below code snippet into worker thread from which you want to update your UI,
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("file", pdfPath);
message.setData(bundle);
handler.sendMessage(message); // pass handler object from activity
put Handler related code into Activity class
Handler handler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
String filePath = msg.getData().getString("file"); // You can change this according to your requirement.
}
};
If you aren't familiar with Handler mechanism then first read following link, it will help you
https://developer.android.com/training/multiple-threads/communicate-ui.html

Removing location updates using a thread

I have a service that constantly polls a webservice for some options. These options basically restart a LocationManager. This restart is done using a custom event which gets fired from a method used inside a thread.
Here is my custom event
public class OptionsChangedEvent extends EventObject {
public OptionsChangedEvent(Object o){
super(o);
}
}
and the custom listener
public interface OptionsChangedListener extends EventListener {
public void optionsChanged(OptionsChangedEvent evt);
}
the thread that runs in the service and polls for new options is the following
private Thread optionsThread = new Thread() {
public void run() {
//Looper.prepare();
while(true) {
String opts = getOptsFromServer();
if(!opts.equals(currentOpts)) updateOpts(opts); //the prob is here
//Looper.loop();
Thread.sleep(10 * 1000) // sleep 10sec
}
}
}
Finally here is how I implement the listener inside my tracker.
locOpts.addOptionsChangedListener(new OptionsChangedListener() {
#Override
public void optionsChanged(OptionsChangedEvent event) {
Log.d("LOCATION_OPTIONS_CHANGED", "SUCCESS");
mLocationManager.removeUpdates(mLocationListener);
mLocationManager.requestLocationUpdates(
provider,
update,
0, mLocationListener
);
}
});
I had the following error which basically says that I need to use Looper.loop and Looper.prepare inside my thread.
12-03 11:31:39.544 26751-26843/com.test.location E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-10370
Process: com.test.location, PID: 26751
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:221)
at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:221)
at android.location.LocationManager.wrapListener(LocationManager.java:844)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:857)
at android.location.LocationManager.requestLocationUpdates(LocationManager.java:454)
at com.test.location.trackers.LocationTracker$2.optionsChanged(LocationTracker.java:93)
at com.test.location.options.LocationTrackerOptions.notifyListeners(LocationTrackerOptions.java:22)
at com.test.location.options.LocationTrackerOptions.fromJSON(LocationTrackerOptions.java:34)
at com.test.location.MainService$5.run(MainService.java:219)
If I uncomment the Looper parts the thread works only once and I cant figure out why this happens.
update
After some investigation I found that code that needs the message queue and creates this problem. Does anyone needed to do something like this? I would like to not change my design here if it possible.
private synchronized void notifyListeners(Object obj) {
for (OptionsChangedListener listener : listeners) {
listener.optionsChanged(new OptionsChangedEvent(obj));
}
}
Do you try to update the UI in your callback method updateOpts ?
Looper prepare & loop using in other way, in case when you want to send tasks from UI thread to the backround thread, so you send message to the thread, and inside the thread process that message in handlemessage event of Handler.
try to avoid UI calls directly from your thread, maybe also try using runOnUIThread(...)
or AsyncTasks onPost to make the proper callback to the UI thread.
The solution was actually very simple. I was missing the callback function.
locOpts.addOptionsChangedListener(new OptionsChangedListener() {
#Override
public void optionsChanged(OptionsChangedEvent event) {
Log.d("LOCATION_OPTIONS_CHANGED", "SUCCESS");
mLocationManager.removeUpdates(mLocationListener);
mLocationManager.requestLocationUpdates(
provider,
update,
0, mLocationListener,
Looper.getMainLooper() // this was the problem
);
}
});

Pause or sleep AsyncTask without affect to UI

Can I sleep or stop AsycTask's execution without affect to UI? Is there any way other than creating a new Thread to achieve this (I am sure this doesn't affect UI though)?
Explanation:
public class MyAsync extends AsyncTask<....>{
#Override
..doInbackground(){
//do something
for(....){
//sleep this Asynctask
//I want to delay my for loop
}
//do something
}
}
Creating a new Thread isn't what I want as follow:
//inside doInBackground()
new Thread(new Runnable(){
#Override
public run(){
for(..){
Thread.sleep(1000);//sleeping for 1 second
}
}
});
//other parts
P.S. I am using AsyncTask in Service to run in background every N seconds.
If you call Thread.sleep(1000) from inside the doInBackground() method, this will not affect the UI since doInBackground() is called on a background thread.

sendBroadcast not working from WorkerThread

i want to send a Broadcast from a FromTowerThread with the following method:
void postToService(final String string){
Handler handler = new Handler();
handler.post(new Runnable(){
#Override
public void run() {
context.sendBroadcast(new Intent(string));
}
});
}
My context is 'this' (my service):
FromTowerThread ftt = new FromTowerThread(this);
(just for completeness my constructor in FromTowerThread):
public FromTowerThread(Context context){
this.context=context;
}
The Error i get is "Can't create handler inside thread that has not called Looper.prepare()".
I don't know how to fix this error, all threads i found about this topic could not help me to understand this.
Thanks in advance!
Chris
change the statement
Handler handler = new Handler();
to
Handler handler = new Handler(Looper.getMainLooper());
Post can only be done from a Handler in a thread that called Looper.prepare().
I'm assuming here that the thread that calls void postToService(final String string) is some type of background thread. Usually the UI thread does call Looper.prepare() meaning that you would have to create the Handler inside the UI thread.
but just as a general suggestion, I'm pretty sure you can just eliminate all of this and just call the broadcast straight away:
void postToService(final String string){
context.sendBroadcast(new Intent(string));
}
The Error i get is "Can't create handler inside thread that has not called Looper.prepare()".
If you are extending Thread, try extending HandlerThread instead. A HandlerThread has a Looper already. (Or you can call Looper.prepare() and Looper.loop() yourself in a regular Thread.)
Otherwise you can do a few things to use the main Thread's Looper. For instance create the Handler in the main Thread and pass it to your worker Thread or even pass a View from the UI Thread and call view.post(Runnable) to execute that Runnable on the UI Thread.

Categories

Resources