I'm developing an android application , my problem is that I can't execute my asyntask class after clicking on a button but it works normally when I called it in my program
I have in logcat the error : "Only the original thread that created a view hierarchy can touch its views.”
here is my class :
ts.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
jr=2;
emp trs=new emp();
trs.execute();
}
});
emp t=new emp();
t.execute();
private class emp extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params) {
try{
url = new URL("....");
HttpURLConnection httpconn = (HttpURLConnection)url.openConnection();
httpconn.connect();
if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK){
BufferedReader input = new BufferedReader(new InputStreamReader(httpconn.getInputStream()),8192);
while ((line = input.readLine()) != null) {
ja = new JSONArray(line);}
for (int i = 0; i < ja.length(); i++) {
JSONObject jo = null;j=0;
jo = (JSONObject) ja.getJSONObject(i);
ch = jo.getString("bgcolor");
ch1=jo.getString("duree_heure");
ch2=jo.getString("debut_heure");
ch4=jo.getString("matiere");
j=Integer.parseInt(ch2);
ch2=trans(j,ch1);
ch5=jo.getString("idsalle");
ch6=salle(ch5);
addvi(v,ch,ch6,ch2,ch4);
}
input.close();
}
}catch (JSONException e){
System.out.print("vérifier !");e.printStackTrace();} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
return null;
}
}
so can anyone helps me please ?
It's caused by the fact that when you are inside doInBackground you are inside another thread too and since it's forbidden to edit/remove/etc views create from another thread (in this case UI thread) it throw this error.
Since you didn't posted the full code, the only thing which could case this problem is addvi(v,ch,ch6,ch2,ch4); so you should use runOnUiThread method of Activity to execute the method from the main thread.
But you should rethink your logic to work better with Asynctask methods onPreExecute / onPostExecute which is used to work with UI and are called and execute in the main thread (UI thread).
P.S To work better with the methods i said above, you should know what means the three generic in the extendsAsyncTask<Params, Progress, Result>
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the background computation.
Result, the type of the result of the background computation.
Edit: As other noticed in comments you have onProgressUpdate too which is invoked by you from doBackground method using publishProgress
you cannot touch or modify view in the doInBackground function of asynctask all UI work need to be done on UI thread or main thread.I think you are doing some UI work so do it in onPostExecute() method
Related
In the ViewPager+Fragment by FragmentPagerAdapter mode. I want to known How to load data for Internet.
I want to implement:
1.Only select the current pager can to load data
2.Only performing the load data once to every pager
I search the some Answers:
userd the callBack method,I see the lifecyle. It Callback after onCreate. After that dont callBack. if load data
so fast . onCreateVie and onActivityCreate don't callBack. View not find. so this method
not improper.
boolean isFist
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isFist&&isVisibleToUser){
// int this load data
}
}
so,who can give me good Solutions? Please Forgive my broken English.
This example, shows how to use AsyncTask:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
So:
onPreExecute - Runs on UI Thread. (do nothing, or put a progress dialog)
doInBackground - Runs on Background Thread. (download data here)
onPostExecute - Runs on UI Thread, recevies the doInBackground results. (show/update data here)
Note: Right now I do not have time to put this example in the context of your specific question, but AsyncTask is your best option.
EXAMPLE:
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
new LoadJsonTask().execute("http://example.com/data.json");
}
private class LoadJsonTask extends AsyncTask<String, Integer, String > {
ProgressDialog dialog ;
protected void onPreExecute (){
// this happens on UI Thread
// dialog, of course, is optional.
dialog = ProgressDialog.show(getActivity() ,"Wait a moment", "Downloading...");
}
protected String doInBackground (String... params){
// this happens on background...
InputStream input = null;
HttpURLConnection connection = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
// download the file
input = connection.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
result.append(line);
}
return result.toString();
} catch (Exception e) {
// handle exceptions :p
return null;
} finally {
// cleanup here
}
}
protected void onPostExecute(String results){
// Do something with results
dialog.dismiss();
}
}
}
I'm trying to update my user interface with information about a background task that's going on with an AsyncTask. Here's my onProgressUpdate() method.
#Override
protected void onProgressUpdate(final String... params) {
Log.d(TAG, "onProgressUpdate()");
StringBuilder currentParam = new StringBuilder();
StringBuilder statusMessage = new StringBuilder();
txtInputFile.setText("Input: " + params[0]);
txtOutputFile.setText("Output: " + params[1]);
txtPercentDone.setText("" + MainActivity.getProgressStatus(statusMessage, currentParam) + "%");
txtStatusMessage.setText(statusMessage);
txtParamName.setText(currentParam);
}
However, none of the TextViews update their text. I am calling publishProgress() in my doInBackground() method. And the log shows that onProgressUpdate() is getting called correctly. I know that the TextViews have been instantiated and are not null. Does anyone know what's going on?
UPDATE:
This may have something to do with the fact that this code is in a nested fragment (the ui being updated). When I show this same fragment as the root, everything is working fine. But I need to have it nested in this situation. Why is that making a difference?
Pass your parameters and context from AsyncTask and then set them using runOnUiThread. If you can't then put your log here to know the issue.
Every publishProgress() are enqueue on the UI thread, so if your doInBackground ends before all yours onProgressUpdate(), you only see your last ui update.
Try to test adding Thread.sleep(MILLISECONDS) to check the concurrency of the ui thread.
#Override
protected Void doInBackground(Void... params) {
for (int i = 0; i < SOME_VALUE ;i++) {
publishProgress(""+i);
try {
Thread.sleep(MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
I'm using this AsyncTask for calling the skype page https://login.skype.com/json/validator?new_username=username for understand if a certain skype contact already exsists.
public class SkypeValidateUserTask extends AsyncTask<String, Void, String>{
protected String doInBackground(String...urls){
String response = "";
for(String url:urls){
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try{
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s="";
while((s=buffer.readLine()) != null){
response+=s;
}
}catch(Exception ex){
ex.printStackTrace();
}
}
return response;
}
public void onPostExecute(String result){
String status="";
try{
JSONObject obj=new JSONObject(result);
status=obj.getString("status");
}catch(Exception ex){
ex.printStackTrace();
}
//Log.i("RISULTATO: ","STATO: "+status);
}
}
The main activity call this task for getting skype validation user result. The code is:
String skype = "name.surname.example";
if(!skype.equalsIgnoreCase("")){
// check if the skype contact exists
SkypeValidateUserTask task = new SkypeValidateUserTask();
task.execute(new String[] {"https://login.skype.com/json/validator?new_username="+skype});
// here I need to obtain the result of the thread
}
My problems are:
I need to get the result of the task (the String status) in the main activity.
After the task.execute call, the next code in main activity is executed without wait for result returned from asynctask.
It is dengerious to use get() method to get the result from async task because It blocks the UI Thread.
use This Thread where I provided a reusable solutionCallback mechanism to get result from async thread without blocking UI Thread
I have implemented that with the help of lapslaz
public JsonData(YourActivityClass activity)
{
this.activity=activity;
mProgressDialog = new ProgressDialog(activity);
}
protected void onPostExecute(String jsondata) {
if (mProgressDialog != null || mProgressDialog.isShowing()){
mProgressDialog.dismiss();
}
if(jsondata!=null) {
activity.yourcallback(jsondata)
}
}
And define the yourcallback() in YourActivityClass
private void yourcallback(String data) {
jsonRecordsData=data;
showRecordsFromJson();
}
Start your AsyncTask on the main thread. In the preExecute method of the AsyncTask, you can start a ProgressDialog to indicate to the user that you're doing something that takes a few seconds. Use doInBackground to perform the long-running task (checking for valid Skype username, in your case). When it is complete, onPostExecute will be called. Since this runs on the UI thread, you can handle the result and perform further actions depending on it. Don't forget to close the ProgressDialog in onPostExecute.
That's why asyncTask is here. You can not make a blocking function call in UI thread because that will make your app unresponsive.
OnPostExcute Method is called on the UI/Main thread. you need to move your logic there to continue analyzing the result.
If your AsyncTask is an inner class of your main activity then you can just call a function in the main activity and pass it the result
Since it looks like it isn't, you can create constructor in your Async and pass it the Context from your main activity so you can pass the variable back to main activity
Also, the purpose of the AyncTask is to not block your UI thread, put your logic in a separate function that the AsyncTask will call
You need to implement a call-back mechanism in your AsyncTask. So instead of this:
task.execute(...);
// use results of task
Your structure should be:
task.execute(...);
// go do something else while task has a chance to execute
public void statusAvailable(String status) {
// use results of task
}
and in onPostExecute:
public void onPostExecute(String result) {
. . .
status=obj.getString("status");
activity.statusAvailable(status);
}
Getting the result out of the AsyncTask is easy . . . just the Google docs don't make it clear how to do it. Here's a quick run down.
task.execute(params);
will start the AsyncTask and pass to the doInBackground method whatever parameters you include. Once doInBackground finishes, it passes the result of its functions to onPostExecute. One would think that onPostExecute would be able to just return whatever you sent it. It doesn't. To get the result of doInBackground, which was sent to onPostExecute you need to call
task.get();
the .get() method automaticlly waits until the task has completed execution and then returns whatever the result of onPostExecute is back to the UI thread. You can assign the result to whatever variable you want and use normally after that - for example
JSONObject skypeStuff = task.get()
Put another way - just like the AsynTask does not start on it's own, it does not return on its own. The same way you need to .execute() from the UI thread, you need to call .get() from the UI thread to extract the result of the task.
#Override
protected InputStream doInBackground(String... url){
try {
InputStream stream = downloadXml(url[0]);
new ParseXml(stream); //for testing porpuses: outputs ok to logcat
return stream;
} catch (IOException e) {
Log.d("dbg","exception");
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(InputStream result) {
if (result != null) {
new ParseXml(result); //crashes the app
}
Log.d("dbg","postexecute triggered ok");
}
Code is pretty self explanatory i think, i tried changing the passing type to just Object and type casted it where needed but it didn't worked either.
Is there anything undocumented in sdk that i should know of ?
obviously, Crash.. You are doing lengthy (also may be network related) operation in MainUI Thread. as onPostExecute() of AsyncTask runs on In MainUI Thread only. So always keep it in doInBackground().
This code line new ParseXml(result); should be in doInBackground() of AsyncTask.
Update:
So complete the Parsing of XML in doInBackground() and only pass the result in onPostExecute() if only you want to reflect the updation on Application UI.
When my users click the login button I want to hit my webservice. I have the following code to do so.
public void onClick(final View view) {
String orgKey = inputCompany.getText().toString();
new getAppInfo().execute("http://example.webservice.com");
Here is my getAppInfo
private class getAppInfo extends AsyncTask<String, Void, String> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
#Override
protected String doInBackground(String... urls) {
String xml = null;
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(urls[0]);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// return XML
return xml;
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
#Override
protected void onPostExecute(String result) {
Document doc = GetDomElement(result); // getting DOM element
NodeList nl = doc.getElementsByTagName("details");
getChildElements(nl);
}
The doBackground is running but the onPostExecute is not. I have moved it out of the on click and it has worked but I need it inside the onClick.
How can I get it to run the onPostExecute inside my onClick?
The syntax is correct you might be getting an exception in the background process, stopping the background thread. put a log statement at the end of your doInBackground or add a catch (Throwable t) to your try.
Have faith - it WILL be called as long as doInBackground completes successfully.
As an aside, you should do your DOM parse in the background as well - at the moment you are doing it in the UI thread which may cause ANR popups.
First, a general pointer - class names in Java are conventionally capitalized CamelCase, method names are lowercase camelCase.
On to your question - are you by any chance exiting the Activity or closing the Dialog that spawned the task? If it works outside that onclick handler, my guess is that something is destroying the Handler object that the AsyncTask is trying to execute that method on.
Try posting a Runnable (which executes the AsyncTask) on the current Activity's Handler.
onPostExecute will always be called once doInBackground is completed. Try to Log something in onPostExecute to confirm this behavior.
add a general catch statement in your doInBackground method.
catch(Exception e){
e.printStackTrace();
}