i have an asyncTask that downloads an image. sometimes it can't download and give this exception java.lang.RuntimeException: An error occurred while executing doInBackground()
Now i want to handle this and when it occurs stop downloading (because i create a notification bar in onPreExecute that show download progress) and Toast a message that download not completed!
#Override
protected Void doInBackground(Void... unused) {
#Override
protected void onPreExecute() {
mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //.... to create a notification
}
downloadPackage(IMG_DIR_URL);//my function to download an imagedo some stuff
return null;
}
protected void onProgressUpdate(Integer... progress) {
// setting progress bar on notification area
//fore example mBuilder.setProgress(100, progress[0], false);
}
In similar case as of yours, I opted following approach:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
Exception exception = null;
protected Long doInBackground(URL... urls) {
try{
//downloading code here..
}catch(SomeException e){
exception = e;
}
return totalSize;
}
protected void onPostExecute(Long result) {
if(exception!=null){
// show toast.
// cancel async task. (this.cancel())
}else{
// no exception while downloading, check for result and take corresponding action on result
}
}
}
just put your code in try/catch block and in catch block you can handle exception and app will never crash: use the below code to handle and get the error,it will give you the methid and class name also the line number of exception.
try {
//do your stuff
} catch (Exception e) {
for (int i = 0; i < e.getStackTrace().length; i++) {
StackTraceElement oStackTace = e.getStackTrace()[i];
String ClassName = oStackTace.getClassName();
String MethodName = oStackTace.getMethodName();
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Log.d("Class Name: " + ClassName + " Method Name: "
+ MethodName, exceptionAsString);
}
}
Related
I want to return a specific string using ksoap2 web service in my android app.
Web service is returning the correct value but the set text is not getting updated once the task is complete. I need to do something (like trying to open the navigation drawer) then its getting updated. Any ideas??
My code is as follows
// Calling the async class
protected void onResume() {
try {
super.onResume();
new RetrieveTimeWS().execute();
}
catch (Exception e)
{
Log.e("Current Time", e.getMessage());
}
}
Following is the Async Task
class RetrieveTimeWS extends AsyncTask<Void, Void, String> {
protected String doInBackground(Void... params) {
String datetime = "";
try {
TextView TVcurrentTime = (TextView) findViewById(R.id.DateTimeNow);
TVcurrentTime.setText("Loading...");
datetime = getDateTimeClass.getDateTime();
TVcurrentTime.setText(datetime);
} catch (Exception e) {
Log.e("Async Task - GetDateTime ", e.getMessage());
}
return datetime;
}
}
The text field shows "Loading..." only till I touch any component on the screen. How can i change the textview to the required string after the web service returns the text.
Thanks in advance.
Laks.
You can't interact with UI not from UI thread. AsyncTask has onPreExecute and PostExecute methods which called from UI thread and you can change UI in it.
class RetrieveTimeWS extends AsyncTask<Void, Void, String> {
TextView TVcurrentTime = (TextView) findViewById(R.id.DateTimeNow);
Exception e;
#Override
protected void onPreExecute() {
super.onPreExecute();
TVcurrentTime.setText("Loading...");
}
protected String doInBackground(Void... params) {
String datetime = "";
try {
datetime = getDateTimeClass.getDateTime();
} catch (Exception e) {
this.e = e;
Log.e("Async Task - GetDateTime ", e.getMessage());
}
return datetime;
}
#Override
protected void onPostExecute(final String s) {
super.onPostExecute(s);
if (e != null) {
TVcurrentTime.setText(s);
}
}
}
You can not do any UI work in background thread. Do it in onPostExecute() method.
This method runs on main thread. So, you can set text in this method.
This is my code: (Some random text to complete question osdifhgsoid hgodfhgo hsdhoigifdshgnvfa oidvojd nobndisfn vbjobsf).
private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
protected Long doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x)
{
textIn.setText("shit! " + x.toString());
}
long i = 10;
return i;
}
}
(Some random text again to complete question(stupid system) dpfgojd ipgsdigjsidoignsdog
public void Listen(){
int count = 0;
TextView msg = MyActivity.msg;
ServerSocket server;
Socket client;
try {
server = new ServerSocket(9797);
Log.d("My log", "server started");
Log.d("My log", "waiting for connnections");
while (started) {
try{
msg.setText("waiting for connection"); <=== here crashing
client = server.accept();
count++;
Log.d("My Log", "Connected");
Log.d("My Log", "aha" + count);
int i = 0;
String data = null;
byte[] bytes = new byte[1024];
InputStream is = client.getInputStream();
OutputStream os = client.getOutputStream();
while (is.available() == 0) {
try{
Thread.sleep(50);
}catch (Exception cc){}
}
is.read(bytes, 0, is.available());
os.write("hala".getBytes());
client.close();
}catch (Exception cc)
{
cc.toString();
}
}
} catch (Exception el) {
el.printStackTrace();
}
}
(Some random text to complete question). Please help
change it via the onPostExecute method!
The purpose of an AsyncTask is to do a long running task in a separate thread and then communicate the result back to the UI thread via onPostExecute().
Also, I'm not sure why you use Long as your return value since you do not seem to be using it. A much better solution would be to have Void as return value and save the exception and use that as an indicator if anything went wrong:
private class DownloadFilesTask extends AsyncTask<String, Integer, Void> {
private Exception exception = null;
#Override
protected Void doInBackground(String... urls) {
try{
Listen();
}
catch (Exception x) {
exception = x;
}
}
#Override
public void onPostExecute(Void result) {
if(exception != null) {
textIn.setText("shit! " + exception.toString());
}
else {
// long running task was completed successfully
}
}
}
Yes, because you are trying to set the TextView inside the doInBackground() method, and this is not allowed.
So there is a solution if you want to set the TextView inside the doInBackground() method, do the UI updating operations inside the runOnUiThread method.
Otherwise, suggestion is to do all the UI display/update related operations inside the onPostExecute() method instead of doInBackground() method of your AsyncTask class.
Good idea would be to return a String in doInBackground(), say exceptionCatched. You can set it to Exception title in catch() block and then in onPostExecuted() just check if(!TextUtils.isEmpty(exceptionCatched)) textIn.setText(exceptionCatched); That's it!
private class DownloadFilesTask extends AsyncTask<Void, Void,Long>{
#Override
protected Long doInBackground(Void... params) {
publishProgress(progress);
//calculate progress and value from your downloading logic
try {
} catch (Exception e) {
return (long) 0;
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
//dis method run deafult on UI thread , so every time u publish ur onProgressUpdate will be called and update ur text here
}
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
if(result==0){
//error occured
}
}
// in case of exception return the result as long value to promt to onPostExceute()
I'm guessing runOnUiThread. You can't update the UI from any other thread than the UI thread.
I am trying to use ProgressDialog. when i run my app the Progress Dialog box show and disappear after 1 second. I want to show it on completion of my process.. Here is my code:
public class MainActivity extends Activity {
android.view.View.OnClickListener mSearchListenerListener;
private ProgressDialog dialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new YourCustomAsyncTask().execute(new String[] {null, null});
}
private class YourCustomAsyncTask extends AsyncTask <String, Void, Void> {
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading....");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show(); //Maybe you should call it in ruinOnUIThread in doInBackGround as suggested from a previous answer
}
protected void doInBackground(String strings) {
try {
// search(strings[0], string[1]);
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
} catch(Exception e) {
}
}
#Override
protected void onPostExecute(Void params) {
dialog.dismiss();
//result
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
return null;
}
}
}
Updated Question:
#Override
public void onCreate(SQLiteDatabase db) {
mDatabase = db;
Log.i("PATH",""+mDatabase.getPath());
mDatabase.execSQL(FTS_TABLE_CREATE);
loadDictionary();
}
/**
* Starts a thread to load the database table with words
*/
private void loadDictionary() {
new Thread(new Runnable() {
public void run() {
try {
loadWords();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private void loadWords() throws IOException {
Log.d(TAG, "Loading words...");
for(int i=0;i<=25;i++)
{ //***//
final Resources resources = mHelperContext.getResources();
InputStream inputStream = resources.openRawResource(raw_textFiles[i]);
//InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
StringBuilder sb = new StringBuilder();
while ((word = reader.readLine()) != null)
{
sb.append(word);
// Log.i("WORD in Parser", ""+word);
}
String contents = sb.toString();
StringTokenizer st = new StringTokenizer(contents, "||");
while (st.hasMoreElements()) {
String row = st.nextElement().toString();
String title = row.substring(0, row.indexOf("$$$"));
String desc = row.substring(row.indexOf("$$$") + 3);
// Log.i("Strings in Database",""+title+""+desc);
long id = addWord(title,desc);
if (id < 0) {
Log.e(TAG, "unable to add word: " + title);
}
}
} finally {
reader.close();
}
}
Log.d(TAG, "DONE loading words.");
}
I want to show ProgressDialogue box untill all words are not entered in the database. This code is in inner calss which extends SQLITEHELPER. so how to can i use ProgressDialogue in that inner class and run my addWords() method in background.
You cannot have this
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
in your doInBackground().
Progress dialog doesn't take priority when there is some other action being performed on the main UI thread. They are intended only when the actions are done in the background. runonUIthread inside doInBackground will not help you. And this is normal behavior for the progressdialog to be visible only for few seconds.
You have two doInBackground() methods inside your AsyncTask Class. Remove the runOnUiThread() from First doInBackground() and move it to second doInBackground() which has #Override annotation.
I don't know whether you wantedly written two doInBackground() methods or by mistake but it is not good to have such confusion between the Method. Your AsyncTask is not calling the first doInBackground() and it will call doInBackground() which has #Override annotation. So your ProgressDialog is dismissed in 1 second of time as it returns null immediately.
I have wrote an app to run an AsyncTask and part of the code is listed as follow. The problem is when the AsyncTask start by execute the code - "new AddImageTask().execute();" in the thread handler, the task will start and everything seems right. However, eventually the app will stay in "doInBackground" method after all code in "doInBackground" method has been executed. The task can't go to "onPostExecute" method. (i.e. can't dismiss the dialog...) What get wrong?
Thanks for the help......
private Handler handleFetchResult = new Handler() {
#Override
public void handleMessage(Message msg) {
progressDialog.dismiss();
Log.d(TAG, "Start handle fetch result");
try {
JSONArray ja = new JSONArray(fetchResult);
Log.d(TAG, "JSON Array Length = " + ja.length());
JSONObject jo = new JSONObject();
for (int i = 0; i < ja.length(); i++) {
jo = ja.getJSONObject(i);
PhotoURLs.add(PAT_url + jo.getString("filePath"));
Log.d(TAG, PhotoURLs.get(i));
}
} catch (JSONException e) {
Log.d(TAG, "Fetch result error: " + e.getLocalizedMessage());
e.printStackTrace();
}
//TODO: display thumbnail
new AddImageTask().execute();
}//void handleMessage
};//Handler handleFetchResult
class AddImageTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
loadThumbnailDialog.show(SitePhotoGallery.this, "Fetch thumbnails from server",
"Loading...", true, true);
Log.d("AddImageTask.onPreExecute","onPreExecute");
}
#Override
protected Void doInBackground(Void... unused) {
// TODO Auto-generated method stub
for (String url : PhotoURLs) {
String filename = url.substring(url.lastIndexOf("/") + 1, url.length());
String thumburl = url.substring(0, url.lastIndexOf("/")+1);
imgAdapter.addItem(LoadThumbnailFromURL(thumburl + filename));
publishProgress();
}
Log.d("AddImageTask.doInBackground","doInBackground");
return null ;
}
#Override
protected void onProgressUpdate(Void... unused) {
super.onProgressUpdate();
imgAdapter.notifyDataSetChanged();
Log.d("AddImageTask.onProgressUpdate","OnProgressUpdate");
}
protected void onPostExecute(Void... unused) {
super.onPostExecute(null);
loadThumbnailDialog.dismiss();
Log.d("AddImageTask.onPostExecute","onPostExecute");
}
}
I think it's because onPostExecute() should take a Void parameter and not a Void... parameter. (You should also specify #Override as Soxxeh pointed out in his/her comment above.)
so basically im trying to parse some data from website using AsyncTask, i want it to get website url from program, update ui with downloaded data and show progressdialog (spinning wheel) so i figured i need to do it like that: (UPDATE): k now its ok with variables but program force closes anyway
private class backgroundDATA extends AsyncTask<String, Void, Void> {
ProgressDialog dialog;
Document doc;
#Override
protected void onPreExecute() {
dialog = dialog.show(Result.this, " ",
" Loading. Please wait ... ", true);
}
#Override
protected Void doInBackground(String... params) {
try {
doc = Jsoup.connect(params[0]).get();
} catch (IOException e){
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
Elements maine;
Elements titleJSOUP;
Elements recipeJSOUP;
Elements instructionsJSOUP;
String recipE;
maine = doc.select("div#recipeContent");
titleJSOUP = doc.select("title");
recipeJSOUP = maine.select("ul.recipe");
instructionsJSOUP = maine.select("p.instructions");
recipE = recipeJSOUP.toString();
drinkNameText.setText("THE "
+ Jsoup.parse(titleJSOUP.toString()).text()
);
dontListenText.setText(Jsoup.parse(titleJSOUP.toString()).text()
);
recipeText.setText(prepareDRINK(recipE));
instructionsText.setText(Jsoup.parse(instructionsJSOUP.toString())
.text());
dialog.dismiss();
}
}
Well this is going to cause a NullPointerException for a start...
#Override
protected void onPreExecute() {
dialog = dialog.show(Result.this, " ",
" Loading. Please wait ... ", true);
}
You can't call dialog.show(...) as dialog will be null.
Call the static ProgressDialog.show(...) method instead.