Creation of New Thread is Giving an error - android

I am new to android i am trying to create a new thread to invoke another method.
But don't why it is throwing the error.
here is my stub
void test()
{
int i=0;
Toast.makeText(getApplicationContext(), "Testing", Toast.LENGTH_SHORT).show();
}
public void Button2_Click(View v)
{
Thread thread = new Thread()
{
#Override
public void run() {
test();
}
};
thread.start();
}

You can't manipulate the UI from other threads than the main thread, and launching a Toast involves the user interface.
change your test function
void test()
{
int i=0;
Log.d("Test","Testing");
}
now if the thread works you will se a log inside LogCat. If you want to display a Toast from another thread, you must use Handler or runOnUiThread.

Do this is Handler
like this http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html

you can not put Toast inside a Thread. Remove your Toast message from your code. It will work fine.

This is how you can do it.
`new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
'
Its a bracket mismatch.

If you absolutely must Toast, you should use the runOnUIThread() method and pass it a new Runnable() anonymous class that Toasts in the run() method.
Irrelevantly, this doesn't seem to make a whole lot of sense. Perhaps you want to make test() static. Maybe post a better idea of what you'd like to do and exactly what error you're getting?

Related

How to wait for webview.post to complete?

In the below code, outside is printed before inside. I want the order to be inside first and then outside. So how do I ensure that the Runnable is finished before the second Log is reached?
webView.post(new Runnable() {
#Override
public void run() {
Log.d("check", "inside");
}
});
// some code needed here
Log.d("check", "outside");
Some code must be inserted where to comment is to achieve this.
EDIT: I am doing all the work in a background service.
[P.S.: Those who are curious as to why I am doing this, it is so because unless I add the webview.post, I keep getting the following error: "All WebView methods must be called on the same thread.". Anyway, this shouldn't affect you from answering the question.]
You might try using a CountDownLatch:
final CountDownLatch latch = new CountDownLatch(1);
webView.post(new Runnable() {
#Override
public void run() {
Log.d("check", "inside");
latch.countDown();
}
});
// some code needed here
latch.await();
Log.d("check", "outside");
However, you wouldn't want to use latch.await() on the UI thread, as that's a blocking method. If you wanted to run this on the UI thread it would be best to replace latch.countDown() with a call to a callback method, which would in turn run Log.d("check", "outside").

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(); [duplicate]

This question already has answers here:
Can't create handler inside thread that has not called Looper.prepare()
(30 answers)
Closed 2 years ago.
I have an Android app running a thread. I want a Toast message to show with a message.
When I do this, I get the below exception:
Logcat trace:
FATAL EXCEPTION: Timer-0
java.lang.RuntimeException: Can't create handler inside thread that has not
called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.widget.Toast$TN.<init>(Toast.java:322)
at android.widget.Toast.<init>(Toast.java:91)
at android.widget.Toast.makeText(Toast.java:238)
Is there a work around for pushing Toast messages from threads to the User Interface?
I got this exception because I was trying to make a Toast popup from a background thread.
Toast needs an Activity to push to the user interface and threads don't have that.
So one workaround is to give the thread a link to the parent Activity and Toast to that.
Put this code in the thread where you want to send a Toast message:
parent.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(parent.getBaseContext(), "Hello", Toast.LENGTH_LONG).show();
}
});
Keep a link to the parent Activity in the background thread that created this thread. Use parent variable in your thread class:
private static YourActivity parent;
When you create the thread, pass the parent Activity as a parameter through the constructor like this:
public YourBackgroundThread(YourActivity parent) {
this.parent = parent;
}
Now the background thread can push Toast messages to the screen.
Android basically works on two thread types namely UI thread and background thread. According to android documentation -
Do not access the Android UI toolkit from outside the UI thread to fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Now there are various methods to solve this problem. I will explain it by code sample
runOnUiThread
new Thread()
{
public void run()
{
myactivity.this.runOnUiThread(new runnable()
{
public void run()
{
//Do your UI operations like dialog opening or Toast here
}
});
}
}.start();
LOOPER
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
AsyncTask
AsyncTask allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.
public void onClick(View v) {
new CustomTask().execute((Void[])null);
}
private class CustomTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... param) {
//Do some work
return null;
}
protected void onPostExecute(Void param) {
//Print Toast or open dialog
}
}
Handler
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.
Message msg = new Message();
new Thread()
{
public void run()
{
msg.arg1=1;
handler.sendMessage(msg);
}
}.start();
Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if(msg.arg1==1)
{
//Print Toast or open dialog
}
return false;
}
});
Here's what I've been doing:
public void displayError(final String errorText) {
Runnable doDisplayError = new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), errorText, Toast.LENGTH_LONG).show();
}
};
messageHandler.post(doDisplayError);
}
That should allow the method to be called from either thread.
Where messageHandler is declared in the activity as ..
Handler messageHandler = new Handler();
From http://developer.android.com/guide/components/processes-and-threads.html :
Additionally, the Android UI toolkit is not thread-safe. So, you
must not manipulate your UI from a worker thread—you must do all
manipulation to your user interface from the UI thread. Thus, there
are simply two rules to Android's single thread model:
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread
You have to detect idleness in a worker thread and show a toast in the main thread.
Please post some code, if you want a more detailed answer.
After code publication :
In strings.xml
<string name="idleness_toast">"You are getting late do it fast"</string>
In YourWorkerThread.java
Toast.makeText(getApplicationContext(), getString(R.string.idleness_toast),
Toast.LENGTH_LONG).show();
Don't use AlertDialog, make a choice. AlertDialog and Toast are two different things.
runOnUiThread(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(), "Status = " + message.getBody() , Toast.LENGTH_LONG).show();
}
});
this works for me
You can simply use BeginInvokeOnMainThread(). It invokes an Action on the device main (UI) thread.
Device.BeginInvokeOnMainThread(() => { displayToast("text to display"); });
It is simple and works perfectly for me!
EDIT : Works if you're using C# Xamarin
I got this error in a JobService from the following code:
BluetoothLeScanner bluetoothLeScanner = getBluetoothLeScanner();
if (BluetoothAdapter.STATE_ON == getBluetoothAdapter().getState() && null != bluetoothLeScanner) {
// ...
} else {
Logger.debug(TAG, "BluetoothAdapter isn't on so will attempting to turn on and will retry starting scanning in a few seconds");
getBluetoothAdapter().enable();
(new Handler()).postDelayed(new Runnable() {
#Override
public void run() {
startScanningBluetooth();
}
}, 5000);
}
The service crashed:
2019-11-21 11:49:45.550 729-763/? D/BluetoothManagerService: MESSAGE_ENABLE(0): mBluetooth = null
--------- beginning of crash
2019-11-21 11:49:45.556 8629-8856/com.locuslabs.android.sdk E/AndroidRuntime: FATAL EXCEPTION: Timer-1
Process: com.locuslabs.android.sdk, PID: 8629
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:203)
at android.os.Handler.<init>(Handler.java:117)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService.startScanningBluetoothAndBroadcastAnyBeaconsFoundAndUpdatePersistentNotification(BeaconScannerJobService.java:120)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService.access$500(BeaconScannerJobService.java:36)
at com.locuslabs.sdk.ibeacon.BeaconScannerJobService$2$1.run(BeaconScannerJobService.java:96)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
So I changed from Handler to Timer as follows:
(new Timer()).schedule(new TimerTask() {
#Override
public void run() {
startScanningBluetooth();
}
}, 5000);
Now the code doesn't throw the RuntimeException anymore.

how to use runOnUiThread without getting "cannot make a static reference to the non static method" compiler error

I have a main class;
ClientPlayer extends Activity {
and a service
LotteryServer extends Service implements Runnable {
when trying to use the RunOnUiThread in the run method of this service I am getting compiler error of, "cannot make a static reference to the non static method"
how to fix this?, how I am using the code is shown here;
#Override
public void run() {
// I tried both ClientPlayer.runOnUiThread and LotteryServer.runOnUiThread
// both don't work
ClientPlayer.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "from inside thread", Toast.LENGTH_SHORT).show();
}
});
} // end run method
runOnUiThread is not a static method.
If u want to run your runnable on UIThread You can use this
Handler handler = new Handler(Looper.getMainLooper());
This will create a handler for UI Thread.
ClientPlayer extends Activity {
.
.
public static Handler UIHandler;
static
{
UIHandler = new Handler(Looper.getMainLooper());
}
public static void runOnUI(Runnable runnable) {
UIHandler.post(runnable);
}
.
.
.
}
Now u can use this anywhere.
#Override
public void run() {
// I tried both ClientPlayer.runOnUiThread and LotteryServer.runOnUiThread
// both don't work
ClientPlayer.runOnUI(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "from inside thread", Toast.LENGTH_SHORT).show();
}
});
} // end run method
There is a very simple solution to the above problem
just make a static reference of your Activity before your onCreat() method
MainActivity mn;
then initialize it in you onCreat() method like this
mn=MainActivity.this;
and after that you just have to use it to call your runOnUiThread
mn.runOnUiThread(new Runnable() {
public void run() {
tv.setText(fns);///do what
}
});
hope it work.
You can get the instance of your Activity, pass it to the service, and use that instead of the class name.
then you can use:
yourActivity.runOnUiThread( ...
Generally we use this method(RunOnUiThread) when we try to update our UI from a working thread. but As you are Using Service Here, runOnMainThread is seems inappropriate as per your situation.
Better to Use Handler here. Handler is an element associated to the thread where is created, you can post a runnable with your code to the Handler and that runnable will be executed in the thread where the Handler was created.
Create a Handler on your Service in his MainThread and post Runnables on
it / send messages to it.

Calling same dialog from different threads

I have an android application with different activities and they all pull data from a web source. This is done by implementing Runnable and creating a thread with the activity as object. The basic class looks like this:
public ActivityX extends Activity implements Runnable {
#Override
public onResume() {
super.onResume();
Thread someThread = new Thread(this);
someThread.start();
}
#Override
public run() {
try {
// pull web content
}
catch(TimeOutException e) {
// >>> create dialog here <<<
// go back to another activity
}
}
}
I tried to create a dialog helper class with a static method that returns the timeout dialog and then call show() like this:
HelperClass.getTimeOutDialog().show();
but the problem is, I can't call it from inside the run() method, as it's in a different thread. If I try to, I will get a runtime exception stating:
Can't create handler inside thread that has not called Looper.prepare()
I need to do this dialog for nearly a dozen of activities and I really want to get around using a Handler objects and sending a message to call the dialog every time. Isn't there an easier way to do this? I just can't think of any right now unfortunately.
My code would look something like this:
handler.handleEmptyMessage(1);
This is to call the handler. And the following would handle the message:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
// show dialog here
}
}
};
Cheers
#Override
public run() {
try {
// pull web content
}
catch(TimeOutException e) {
runOnUiThread(new Runnable(){
#Override
public void run() {
// >>> create dialog here <<<
// go back to another activity
}
}
}
}
Try the one above if you don't want to use Handler.
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
// show dialog here
}
}
};
Is this code a part of your activity and not in a thread? If it is a part of your non Ui thread, it would give you the error message. Make sure the handler instance is created in your UI thread because a handler contains an implicit reference to the thread they get created in.

cant create handler inside thread that has not called looper.prepare

Note : I know there are many questions related to this, but still I am not convince, so asking.
I am getting cant create handler inside thread that has not called looper.prepare when I try to show the dialog.
Here is my code...
//this method is called from a different method based on some condition which is inturn called on click a button
private void download() {
thread = new Thread() {
public void run() {
/**** Downloads each tour's Tour.plist file ****/
try {
// do many heavy operations here, like download,
//calling web webvice and starting another activity
This comes at the end
Intent toAudio = new Intent(TourDescription.this,Audio.class);
startActivity(toAudio);
} catch (Exception e) {
}
}
};
thread.start();
}
Now before this actity gets called I am trying to show a dialog. I am trying to place that just before calling Intent.
Can any body please tell me how to do this, as I am not understanding how to solve this
you cannot show a dialog from a child thread.
A dialog can only be showed from within the UI thread/main Thread.
try this from inside the child thread
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO show dialog....
}
});

Categories

Resources