I am getting error in doing a internet resource getting in thread .
i get this error in logcat :
09-04 21:05:32.916 1480-1493/abc.digicare.sms1 E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-78
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:317)
at android.widget.Toast.<init>(Toast.java:91)
at android.widget.Toast.makeText(Toast.java:233)
at abc.digicare.sms1.MyActivity$1.run(MyActivity.java:45)
at java.lang.Thread.run(Thread.java:856)
my code is this : calling this function from a button click .
public void GetData(View v) {
Toast.makeText(getApplicationContext(), "first", Toast.LENGTH_SHORT).show();
p=ProgressDialog.show(getApplicationContext(),"Digicare","Wait . . .");
try {
Runnable myrun = new Runnable() {
#Override
public void run() {
String acc = "";
if (chckbx_cus.isChecked() && !(chckbx_ven.isChecked()) && !(chckbx_emp.isChecked())) {
acc = "cus";
} else if (chckbx_ven.isChecked() && !(chckbx_cus.isChecked()) && !(chckbx_emp.isChecked()))
Toast.makeText(getApplicationContext(), acc, Toast.LENGTH_SHORT).show();
final String facc = acc;
GetList GL = new GetList();
//Toast.makeText(getApplicationContext(),txt_ip.getText(),Toast.LENGTH_SHORT).show();
obj = GL.GetAccounts(getApplicationContext(), facc, "GetAccounts", "192.168.1.111");
mhandler.sendEmptyMessage(0);
}
};
Thread th = new Thread(myrun);
th.start();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "from here " + e.toString(), Toast.LENGTH_LONG).show();
}
mhandler = new Handler() {
#Override
public void handleMessage(Message msg) {
p.dismiss();
}
};
}
the function which is called from other class is for getting data from a asp.net web service
It seems that you are trying to display a Toast from a background thread. Move the Handler creation code before the try-catch block and use a final modifier so that you can access the handler from within the Runnable. Then in the runnable call
mhandler.post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), acc, Toast.LENGTH_SHORT).show();
}
});
Related
I am learning Android bluetooth programming. I copied most of this code from Google's Android developer website for learning. The idea is listening for connection on server is done in a new thread without blocking the UI thread. When connection request is received then connection is done on another thread and finally communication is done on another thread.
The problem is when I start the listening thread from UI thread, it block automatically and no UI is displayed (freezes). Here is the sample code:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
setContentView(R.layout.activity_main);
...
badapter = BluetoothAdapter.getDefaultAdapter();
if (badapter == null) {
Toast.makeText(this, "No bluetooth device.", Toast.LENGTH_SHORT).show();
return;
}
if (!badapter.isEnabled()) {
Toast.makeText(this, "Bluetooth is disabled.", Toast.LENGTH_SHORT).show();
return;
}
pairedDevices = new HashMap<String, String>();
discoveredDevices = new HashMap<String, String>();
showDevices();
registerBroadcastReceiver();
//this thread blocks UI thread
ListenThread listen = new ListenThread();
listen.run();
}
And the listen thread:
public class ListenThread extends Thread {
MainActivity main;
CommunicateThread communicateThread;
private final BluetoothServerSocket serverSocket;
public ListenThread() {
main = MainActivity.getInstance();
BluetoothServerSocket tmp = null;
try {
tmp = main.badapter.listenUsingRfcommWithServiceRecord(main.NAME, main.MYUUID);
} catch (final IOException e) {
main.handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
serverSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
//keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = serverSocket.accept();
} catch (final IOException e) {
main.handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
break;
}
// If a connection was accepted
if (socket != null) {
//call communication thread once connection is established
communicateThread = new CommunicateThread(socket);
communicateThread.run();
try {
serverSocket.close();
} catch (final IOException e) {
main.handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
break;
}
}
}
}
You are calling listen.run() on the main thread which makes it run on the main thread. You should call listen.start() which will spawn off a separate thread where the run() method will be executed.
The Runnable given to the handler will be executed on the main thread though as the Handler is for the main thread.
I had the same problem. What I understand is that every time you make a hardware call, in this case, the Bluetooth, you should do it in another thread. I moved the isEnabled() call to other thread and it solved the problem.
This question already has answers here:
How do you display a Toast from a background thread on Android?
(14 answers)
Closed 9 years ago.
How to add a toast method inside a thread. I want to debug by replacing the system.out with a toast method to display results to the display.
I know that using the application Context from within the thread, like so:
Toast.makeText(getApplicationContext(), "help", Toast.LENGTH_LONG).show();
will not work.
I don't know how to use the Runnable with the Toast call and calling runOnUiThread(runnable) from the Thread
Could someone help me out.
public class NetworkServer extends Thread
{
DatagramSocket mSocket = null;
boolean isFinish = false;
private SimplestPossibleActivity activity;
public NetworkServer(SimplestPossibleActivity activity)
{
this.activity = activity;
}
public void run()
{
try
{
Log.d("UDP", "Listening");
mSocket = new DatagramSocket( 2010); //4444
mSocket.setBroadcast(true);
while (!isFinish)
{
Log.d("UDP", "C: socket create success");
byte[] recvbuffer = new byte[12];
DatagramPacket packet = new DatagramPacket(recvbuffer,recvbuffer.length);
Log.d("UDP", "receiving...");
mSocket.receive(packet);
Log.d("UDP", "received packet");
ByteBuffer bb = ByteBuffer.allocate(recvbuffer.length).order(ByteOrder.LITTLE_ENDIAN);
bb.put(recvbuffer);
bb.rewind();
//System.out.println(bb.getFloat());
//System.out.println(bb.getFloat());
//System.out.println(bb.getFloat());
Bundle data = new Bundle();
data.putFloat("latitude", bb.getFloat());
data.putFloat("longitude", bb.getFloat());
data.putFloat("altitude", bb.getFloat());
Message msgHandle = new Message();
msgHandle.setData(data);
mhandler.sendMessage(msgHandle);
} //end while
} catch (Exception e) {
Log.e("UDP", "C: Error", e);
}
}
private Handler mhandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
Bundle data = msg.getData();
Log.d("NetworkServer","adding position" + "lat = " + data.getFloat("latitude") +
"lon = " + data.getFloat("longitude") +
"alt = " + data.getFloat("altitude"));
activity.addPosition(data.getFloat("latitude"),
data.getFloat("longitude"),
data.getFloat("altitude"));
}
};
}
Use library Xdroid:
dependencies {
compile 'com.shamanland:xdroid-toaster:0.2.4'
}
There are quite good approaches:
Context variable is not required.
runOnUiThread() is not required.
Just invoke the single method!
// using the resource string
Toaster.toast(R.string.my_msg);
// or hard-coded string
Toaster.toast("Hello Xdroid!");
There are more examples here: https://github.com/shamanland/xdroid-toaster-example
You can do it like this
Handler handler = new Handler(); //Before your Thread
//Within your thread
handler.post(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(), "help", Toast.LENGTH_LONG).show();
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
//pick one:
//if activity
Toast.makeText(YOURACTIVITYNAME.this, "help", Toast.LENGTH_LONG).show();
//if fragment
Toast.makeText(getActivity(), "help", Toast.LENGTH_LONG).show();
} catch (final Exception e) {
}
}
});
In my application I want to check the network status on device,If no network connectivity is detected on device the i want to show a toast saying no network connection and then exit the application.And if the connection is detected on device then i have to load a list from webservice and display it on screen
I have done following code in onCreate function of application.It is running on emulator but not on real device.The reason for this to showANR on device is i am trying to handle so many threads on UI which is not appreciated in android.Please guide me how to do this using AsyncTask.
any code snippet or link to tutorial or suggestions will be helpful to me
boolean connected = false;
ConnectivityManager connectivitymanager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkinfo = connectivitymanager.getActiveNetworkInfo();
connected = networkinfo != null && networkinfo.isAvailable()
&& networkinfo.isConnected();
Log.v("Message ", connected + "");
Log.v("Message ", networkinfo.getReason());
//Toast.makeText(CategoryActivity.this, connected + "", 2000).show();
//connected = false;
Log.v("Message 1", connected + "");
if (connected == false) {
CategoryActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// Log.v("Message ", connected + "");
Toast.makeText(CategoryActivity.this,
"No Internet Connection detected on device", 3000).show();
}
});
Handler handler1 = new Handler();
handler1.postDelayed(new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
finish();
System.exit(0);
}
}), 4000);
} else {
CategoryArray = new JSONArray();
final ProgressDialog pd = ProgressDialog.show(
CategoryActivity.this, "", "Loading...", false, true);
pd.setIcon(getResources().getDrawable(R.drawable.icon));
new Thread() {
public void run() {
try {
sleep(5000);
// Log.v("TAG","in try block");
} catch (Exception e) {
// Log.e("tag", e.getMessage());
}
pd.dismiss();
// Log.v("TAG","progress dismiss");
}
}.start();
handler.postDelayed(new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
CategoryArray = CW
.getCategory("http://www.balajeebazaar.com/RestServiceImpl.svc/categorydetails");
// TODO: handle exception
for (int i = 0; i <= CategoryArray.length() - 1; i++) {
try {
String[] val = new String[3];
Log.v("category array : ",
CategoryArray.getString(i));
val = CategoryArray.getString(i).split(",");
CategoryID.add(i, val[0]);
CategoryList.add(i, val[1]);
val = null;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
adapter = new CategoryListAdapter(CategoryActivity.this,
CategoryList);
list.setAdapter(adapter);
}
}), 5000);
Thanks
EDIT
ERROR/AndroidRuntime(5486): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception
ERROR/AndroidRuntime(5486): java.lang.RuntimeException: An error occured while executing doInBackground()
ERROR/AndroidRuntime(5486): at android.os.AsyncTask$3.done(AsyncTask.java:200)
ERROR/AndroidRuntime(5486): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:234)
ERROR/AndroidRuntime(5486): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:258)
ERROR/AndroidRuntime(5486): at java.util.concurrent.FutureTask.run(FutureTask.java:122)
ERROR/AndroidRuntime(5486): at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
ERROR/AndroidRuntime(5486): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
ERROR/AndroidRuntime(5486): at java.lang.Thread.run(Thread.java:1060)
ERROR/AndroidRuntime(5486): Caused by: java.lang.ArrayIndexOutOfBoundsException
ERROR/AndroidRuntime(5486): at com.ecommerce.balajeebazaar.CategoryActivity$Loader.doInBackground(CategoryActivity.java:181)
ERROR/AndroidRuntime(5486): at com.ecommerce.balajeebazaar.CategoryActivity$Loader.doInBackground(CategoryActivity.java:1)
ERROR/AndroidRuntime(5486): at android.os.AsyncTask$2.call(AsyncTask.java:185)
11-18 18:30:07.582: ERROR/AndroidRuntime(5486):
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
ERROR/AndroidRuntime(5486): 4 more
I suggest you read up on the AsyncTask yourself before applying the solution I have posted below, in order to better understand what is going on.
This is what you need in your Activity (it must replace all the code you posted):
boolean connected = false;
ConnectivityManager connectivitymanager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkinfo = connectivitymanager.getActiveNetworkInfo();
connected = networkinfo != null && networkinfo.isAvailable()
&& networkinfo.isConnected();
Log.v("Message ", connected + "");
Log.v("Message ", networkinfo.getReason());
//Toast.makeText(CategoryActivity.this, connected + "", 2000).show();
//connected = false;
Log.v("Message 1", connected + "");
if (connected == false) {
Toast.makeText(CategoryActivity.this, "No Internet Connection detected on device", Toast.LENGTH_LONG ).show();
finish();
} else {
new Loader().execute();
}
This is the AsyncTask which should be an inner class of your Activity:
private class Loader extends AsyncTask<Void, Void, Void> {
final ProgressDialog pd;
#Override
protected void onPreExecute() {
pd = ProgressDialog.show( CategoryActivity.this, "", "Loading...", false, true);
pd.setIcon(getResources().getDrawable(R.drawable.icon));
super.onPreExecute();
}
#Override
protected Void doInBackground( Void... arg0 ) {
CategoryArray = new JSONArray();
CategoryArray = CW.getCategory("http://www.balajeebazaar.com/RestServiceImpl.svc/categorydetails");
for (int i = 0; i <= CategoryArray.length() - 1; i++) {
try {
String[] val = new String[3];
Log.v("category array : ", CategoryArray.getString(i));
val = CategoryArray.getString(i).split(",");
CategoryID.add(i, val[0]);
CategoryList.add(i, val[1]);
val = null;
} catch (JSONException e) {
e.printStackTrace();
}
}
adapter = new CategoryListAdapter(CategoryActivity.this, CategoryList);
return null;
}
#Override
protected void onPostExecute( Void result ) {
pd.dismiss();
list.setAdapter(adapter);
super.onPostExecute( result );
}
}
Note
I wasn't able to check if the above actually works - but it should put you on the right track.
A nice tutorial on AsyncTasks and Handlers.
In really short, the idea of AsyncTask - you make a private class which extends AsyncTask in your Activity.
Doing this, you automatically get access to this Activities UI Thread from the AsyncTask class.
In AsyncTaks there are a couple of methods you should pay attention to. They are explained here.
What you should know is that only doInBackground() is executed in a separate Thread. Everything else is invoked on the UI thread of the Activity, where your AsyncTask is defined.
Simple scenario:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// stuff
new MyAsyncTask().execute(); //this should be invoked only once
}
private class MyAsyncTask() extends AsyncTask<Void, Void, <TypeOfResult Or Void>> {
#Override //executed on the UI thread of MyActivity
protected void onPreExecute() {
super.onPreExecute();
//prepare some stuff
}
#Override //executed in a separate Thread. This thread is automatically handled by AsyncTask
protected <TypeOfResult or Void> doInBackground(Void... params) {
//long operation
}
#Override //executed on the UI thread of MyActivity
protected void onPostExecute(<TypeOf Result Or Void>) {
super.onPostExecute(result);
// do stuff with result from long operation
}
}
}
You don't necessarily need an AsyncTask, you can use regular Java threading to accomplish what you need (far easier for a background task like this).
I have a very simple UI and i need to constantly run a check process, so I am trying to use a Thread with a while loop.
When I run the loop with nothing but a Thread.sleep(1000) command, it works fine, but as soon as I put in a display.setText(), the program runs for a second on the emulator then quits. I cannot even see the error message since it exits so fast.
I then took the display.setText() command outside the thread and just put it directly inside onCreate, and it works fine (so there is no problem with the actual command).
here is my code, and help will be greatly appreciated.
Thank you!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
on=(Button) findViewById(R.id.bon);
off=(Button) findViewById(R.id.boff);
display=(TextView) findViewById(R.id.tvdisplay);
display2=(TextView) findViewById(R.id.tvdisplay2);
display3=(TextView) findViewById(R.id.tvdisplay3);
stopper=(Button) findViewById(R.id.stops);
stopper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(boo=true)
{
boo=false;
display3.setText("System Off");
}
else{
boo=true;
}
}
});
Thread x = new Thread() {
public void run() {
while (boo) {
display3.setText("System On");
try {
// do something here
//display3.setText("System On");
Log.d(TAG, "local Thread sleeping");
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "local Thread error", e);
}
}
}
};
display3.setText("System On");
display3.setText("System On");
x.start();
}
You can't update the UI from a non-UI thread. Use a Handler. Something like this could work:
// inside onCreate:
final Handler handler = new Handler();
final Runnable updater = new Runnable() {
public void run() {
display3.setText("System On");
}
};
Thread x = new Thread() {
public void run() {
while (boo) {
handler.invokeLater(updater);
try {
// do something here
//display3.setText("System On");
Log.d(TAG, "local Thread sleeping");
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "local Thread error", e);
}
}
}
};
You could also avoid a Handler for this simple case and just use
while (boo) {
runOnUiThread(updater);
// ...
Alternatively, you could use an AsyncTask instead of your own Thread class and override the onProgressUpdate method.
Not 100% certain, but I think it is a case of not being able to modify UI controls from a thread that did not create them?
When you are not in your UI thread, instead of display3.setText("test") use:
display3.post(new Runnable() {
public void run() {
display3.setText("test");
{
});
You should encapsulate this code in an AsyncTask instead. Like so:
private class MyTask extends AsyncTask<Void, Void, Void> {
private Activity activity;
MyTask(Activity activity){
this.activity = activity;
}
protected Long doInBackground() {
while (true){
activity.runOnUiThread(new Runnable(){
public void run(){
display3.setText("System On");
}
});
try{
Thread.sleep(1000);
}catch (InterruptedException e) {
Log.e(TAG, "local Thread error", e);
}
}
}
Then just launch the task from your onCreate method.
In non-UI thread,you can't update UI.In new Thread,you can use some methods to notice to update UI.
use Handler
use AsyncTask
use LocalBroadcast
if the process is the observer pattern,can use RxJava
I have recently experimented with creating an easy way to open a ProgressDialog up in a second thread, so if the main thread freezes the dialog will keep working.
Here is the class:
public class ProgressDialogThread extends Thread
{
public Looper ThreadLooper;
public Handler mHandler;
public ProgressDialog ThreadDialog;
public Context DialogContext;
public String DialogTitle;
public String DialogMessage;
public ProgressDialogThread(Context mContext, String mTitle, String mMessage)
{
DialogContext = mContext;
DialogTitle = mTitle;
DialogMessage = mMessage;
}
public void run()
{
Looper.prepare();
ThreadLooper = Looper.myLooper();
ThreadDialog = new ProgressDialog(DialogContext);
ThreadDialog.setTitle(DialogTitle);
ThreadDialog.setMessage(DialogMessage);
ThreadDialog.show();
mHandler = new Handler();
Looper.loop();
}
public void Update(final String mTitle, final String mMessage)
{
while(mHandler == null)
synchronized(this) {
try { wait(10); }
catch (InterruptedException e) {
Log.d("Exception(ProgressDialogThread.Update)", e.getMessage() == null ? "MISSING MESSAGE" : e.getMessage());
}
}
mHandler.post(new Runnable(){
#Override
public void run() {
ThreadDialog.setTitle(mTitle);
ThreadDialog.setMessage(mMessage);
}});
}
public void Dismiss()
{
while(ThreadDialog == null || mHandler == null)
synchronized(this) {
try { wait(10); }
catch (InterruptedException e) {
Log.d("Exception(ProgressDialogThread.Dismiss)", e.getMessage() == null ? "MISSING MESSAGE" : e.getMessage());
}
}
mHandler.post(new Runnable(){
#Override
public void run() {
ThreadDialog.dismiss();
}});
}
public void Continue()
{
while(ThreadLooper == null || mHandler == null)
synchronized(this) {
try { wait(10); }
catch (InterruptedException e) {
Log.d("Exception(ProgressDialogThread.Continue)", e.getMessage() == null ? "MISSING MESSAGE" : e.getMessage());
}
}
mHandler.post(new Runnable(){
#Override
public void run() {
ThreadLooper.quit();
}});
}
However it sometimes work perfectly but other times the application simply freezes and crashes eventually.
Here is an example of use:
ProgressDialogThread thread = new ProgressDialogThread(this, "Loading", "Please wait...");
thread.start();
// Do Stuff
thread.Dismiss();
thread.Continue();
It generates a lot of warning and even some crashes sometimes:
eg.
Handler: Sending message to dead thread....
and exceptions like
ANR in ......
Reason: keyDispatchingTimedOut
Thanks for any help,
Alex.
When wanting to do stuff in separate threads on Android, you should look at the AsyncTask class. You can read about it here: http://developer.android.com/resources/articles/painless-threading.html
Googling (or searching here on Stack Overflow) will also give you plenty of information on how to use it it the above link isn't sufficient :)