Start AsyncTask inside of a Thread [duplicate] - java

This question already has answers here:
Start Async Task within a worker thread
(5 answers)
Closed 8 years ago.
I want to start a simple process of getting the HTML code of a webpage from inside an AsyncTask, because when it's from the new Thread the UI freezes for few moments, how can I do it?
public void loadHTML(View vL) {
final String ss = (et.getText().toString());
new Thread(new Runnable() {
#Override
public void run() {
try {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(new HttpGet(ss));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
final String responseString = out.toString();
tvW.post(new Runnable() {
#Override
public void run() {
tvW.setText(responseString);
}
});
Log.v("DYRA BYRA", responseString);
} else {
response.getEntity().getContent().close();
}
} catch (Exception e) {
}
}
}).start();
}
I want this part tvW.post(new Runnable() {
#Override
public void run() {
tvW.setText(responseString);
}
});
to be in AsyncTask

Uh i don't think you need an asynctask but a run on ui thread
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
tvW.setText(responseString);
}
});

You have to sync your Thread with the UI-Thread. Because all UI relevant operations like writing to an TextView have to be done on the UI-Thread. Therefor you should use the Handler class.
Handler myHandler = new Handler();
Now replace this code:
tvW.post(new Runnable() {
#Override
public void run() {
tvW.setText(responseString);
}
});
With this one:
myHandler.post(new Runnable() {
#Override
public void run() {
tvW.setText(responseString);
}
});
Note that your Handler class have to be declared on the UI-Thread to get connected.

That's what I wanted to do
public void loadHTML(View vL) {
new getCode().execute();
}
private class getCode extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
final String ss = (et.getText().toString());
try {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(new HttpGet(ss));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
Log.v("DYRA BYRA", responseString);
} else {
response.getEntity().getContent().close();
}
} catch (Exception e) {
}
return null;
}
protected void onPostExecute(String result) {
tvW.setText(responseString);
}
}
the UI still freezes for like half second, but perhaps that's because the received HTML is extremely long

Related

FirebaseMessagingService is not getting called in AsyncTask's doInBackground

I have push Notification and I want to update realm objects when the phone gets a notification but when I try launch this:
RealmModelActiveUser actUser= realm.where(RealmModelActiveUser.class).equalTo("id",1).findFirst();
int myid= actUser.getUser().getUser_id();
new ServerBackgroundDownloadConversations(getApplicationContext()) {
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (!result.equals("Error")) {
Log.i("Conversation", "UPDATED");
}
}
}.execute(myid);
The program jumps into the constructor ServerBackgroundDownloadConversations(getApplicationContext()) but doesn't call doInBackground and I don't know why.
My AsyncTask:
public class ServerBackgroundCreateConversation extends AsyncTask<RealmModelConversations,Void,String> {
Context context;
Handler handler;
String out= "";
#SuppressLint("HandlerLeak")
public ServerBackgroundCreateConversation(Context context) {
this.context = context;
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle bundle= msg.getData();
if (bundle!=null){
out = (String) bundle.get("response");
} else {
out= "Error";
}
}
};
}
#Override
protected String doInBackground(RealmModelConversations... params) {
RealmModelConversations newConv = params[0];
UploadImageApacheHttp uploadTask = new UploadImageApacheHttp();
uploadTask.doFileUpload(newConv.getWork(newConv.getIntWork()), newConv, handler);
while (out.equals("")){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return out;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(String result) {
if (!result.equals("]") || !result.equals("")){
/// prihlási nového user aj do active (login/register)
CreateNewConversation(result);
} else {
result="Error";
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
private void CreateNewConversation(String result){
Realm realm= Realm.getDefaultInstance();
try {
Gson gson = new Gson();
Type typeConv = new TypeToken<JsonSablonaConversations>() {
}.getType();
JSONObject pom;
JSONArray parentArray = new JSONArray(result);
JSONObject finalObject = parentArray.getJSONObject(0);
JsonSablonaConversations conversation = gson.fromJson(finalObject.toString(), typeConv);
final RealmModelConversations NewUserConv = new RealmModelConversations();
NewUserConv.setId_dialog(conversation.getId_dialog());
NewUserConv.setDate(conversation.getDate());
NewUserConv.setKey(conversation.getKey());
NewUserConv.setId_user(conversation.getId_user());
NewUserConv.setId_user2(conversation.getId_user2());
NewUserConv.setMeno(conversation.getMeno());
NewUserConv.setMeno2(conversation.getMeno2());
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
try {
realm.copyToRealmOrUpdate(NewUserConv);
} catch (Exception e) {
int pom=4;
}
RealmResults<RealmModelConversations> ru= realm.where(RealmModelConversations.class).findAll();
}
});
}
catch (Exception e) {
int ppp=4;
ppp++;
}finally {
realm.close();
}
}
}
I try calling this ↑ from an external thread which is called from a Service, but my AsyncTask has handler and handler needs to be in runOnUIthread and in Thread. I can't get Activity because the thread is called from a Service which doesn't have access to Activity.
I solved my problem with this code
public String postData(int myUserId) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.gallopshop.eu/OFY/getConversations.php");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("id", Integer.toString(myUserId)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
String responseStr = EntityUtils.toString(response.getEntity());
return responseStr;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
return null;
}
I will try to put this method & after this method into simply thread, But maybe it's not needed because it's in a service.
Question - Do I put this into Thread or do you think it'll affect the performance of the app?

Java Interface Callback on Android

I am currently trying to make an android app that basically downloads strings from a url. But I want to make it object oriented. My mainActivity gets string from webService which downloads string when button is clicked. But I am not good at interfaces and callbacks. What should I do to make this code run?
public class MainActivity extends Activity implements WebServiceInterface{
private TextView textView;
private Button readWebPage;
private WebService service;
private WebServiceInterface webServiceInterface;
private String response;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.TextView01);
readWebPage = (Button) findViewById(R.id.readWebpage);
service = new WebService();
readWebPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
service.execute(new String[]{"http://google.com/"});
onSuccess(response);
}
});
}
#Override
public void onSuccess(String response) {
textView.setText(Html.fromHtml(response));
}
#Override
public void onFail(Exception ex) {
textView.setText(ex.getLocalizedMessage());
}
}
public class WebService extends AsyncTask<String, Void, String> {
private WebServiceInterface webServiceInterface;
#Override
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;
}
webServiceInterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webServiceInterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
public interface WebServiceInterface {
void onSuccess(String response);
void onFail(Exception ex);
}
you need to create one public method for set webServiceInterface in WebService class like
public setWebServiceInterface (WebServiceInterface listener)
{
this.webServiceInterface =listener;
}
in MainActivity activity call this method and pass argument this
service.setWebServiceInterface (this);
in WebService class in onPostExecute Method call
webServiceInterface.onSuccess(s);
Add WebService (WebServiceInterface webServiceInterface) in your AsyncTask as a constructor.
service = new WebService(new WebServiceInterface (){
void onSuccess(String response){
//do your stuff
}
void onFail(Exception ex){
//do your stuff
}
});
and in your asynctask
public class WebService extends AsyncTask<String, Void, String> {
public WebService (WebServiceInterface webServiceInterface){
this.webinterface= webServiceInterface;
}
private WebServiceInterface webinterface;
#Override
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;
}
webinterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webinterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
I have found the problem, it is because of runOnUiThread is missing.

How can I set doInbackground finish its task before continuing the mainActivity?

These are my MainActivity:
database_connector wp_terms = new database_connector("SELECT * FROM `dse120071750`.`wp_terms` ",progressDialog,this);
wp_terms.execute();
wp_terms.onPreExecute();
try {
for (int i=0; i<wp_terms.getJsonArray().length(); i++){
JSONObject obj = wp_terms.getJsonArray().getJSONObject(i);
this.wp_terms.put(obj.getString("term_id"), obj.getString("name"));
}
} catch (JSONException e) {
e.printStackTrace();
}
DatabaseConnector:
package hk.hoome.www.mobilehoome;
public class database_connector extends AsyncTask<Void,Void, Void> {
//String mode;
HttpResponse response;
String sql;
JSONArray jsonArray;
searchPage searchPage;
public database_connector(String sql, searchPage searchPage){
//this.mode = mode;
this.sql = sql;
this.searchPage = searchPage;
jsonArray = new JSONArray();
}
#Override
protected Void doInBackground(Void... params) {
connect();
publishProgress();
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
}
public void connect() {
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(1);
nameValuePair.add(new BasicNameValuePair("sql", sql));
//nameValuePair.add(new BasicNameValuePair("mode", mode));
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://www.hoome.hk/hoomeMobileApps/connectDB.php");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair, "UTF-8"));
response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
String entityResponse = EntityUtils.toString(httpEntity);
Log.e("Entity Response ", entityResponse.substring(2));
jsonArray = new JSONArray(entityResponse.substring(2));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
public JSONArray getJsonArray(){
return jsonArray;
}
}
When I ran this code, for (int i=0; i<wp_terms.getJsonArray().length(); i++){ this results in a nullPointerException.
I believe that this is because doInbackground hasn't finished its process but mainActivity keeps running. How can I set that doInbackground has to be done before continue running the mainActivity?
SOLUTION?
try {
while (wp_posts.getJsonArray().equals(null))
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
is this a good solution?
Use a callback in your database connector class and pass the completion callback. For the simplicity I'm using Runnable interface. In general, try to have your own interface and also to pass the params between the background thread and the main thread over your custom interface.
package hk.hoome.www.mobilehoome;
public class database_connector extends AsyncTask<Void,Void, Void> {
//String mode;
HttpResponse response;
String sql;
JSONArray jsonArray;
searchPage searchPage;
private Runnable activityCallback;
public void setCallback(Runnable callback) {
this.activityCallback = callback;
}
public database_connector(String sql, searchPage searchPage){
//this.mode = mode;
this.sql = sql;
this.searchPage = searchPage;
jsonArray = new JSONArray();
}
#Override
protected Void doInBackground(Void... params) {
connect();
publishProgress();
return null;
}
protected void onPostExecute(Void result) {
if(activityCallback != null) {
activityCallback.run();
}
}
#Override
protected void onProgressUpdate(Void... values) {
}
public void connect() {
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(1);
nameValuePair.add(new BasicNameValuePair("sql", sql));
//nameValuePair.add(new BasicNameValuePair("mode", mode));
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://www.hoome.hk/hoomeMobileApps/connectDB.php");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair, "UTF-8"));
response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
String entityResponse = EntityUtils.toString(httpEntity);
Log.e("Entity Response ", entityResponse.substring(2));
jsonArray = new JSONArray(entityResponse.substring(2));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
public JSONArray getJsonArray(){
return jsonArray;
}
}
In your MainActivity
database_connector wp_terms = new database_connector("SELECT * FROM `dse120071750`.`wp_terms` ",progressDialog,this);
wp_terms.setCallback(new Runnable() {
public void run() {
try {
for (int i=0; i<wp_terms.getJsonArray().length(); i++){
JSONObject obj = wp_terms.getJsonArray().getJSONObject(i);
this.wp_terms.put(obj.getString("term_id"), obj.getString("name"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
wp_terms.execute();
I also faced the same problem in one of my project, this is what might help you
public class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(String...params) {
String result;
//background tasks here.
return result;
}
protected void onPostExecute(String result) {
//task after doInBackground here.
}
}
doInBackground():
Override this method to perform a computation on a background thread.
onPostExecute():
Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).
This method won't be invoked if the task was cancelled.
Parameters
result The result of the operation computed by doInBackground(Params...)
perform the background task in doInBackground method and the task after the background task(displaying toast or dialog) in onPostExecute(String result) method.
The result returned from doInBackground(String...params)method will be received as parameter in onPostExecute(String result) method in result parameter.
To use this code segment, from your main activity call new DownloadFilesTask().excute(param1,param2,...,paramn).
This parameters will be received in doInBackground(String...params) in params.
Write in comment if you face any problem.
Happy coding!!!

How to get out an httpGet response from a Thread Android

I have this Thread on a Fragment
Thread trd = new Thread(new Runnable(){
#Override
public void run(){
HttpClient hc = new DefaultHttpClient();
HttpGet post = new HttpGet("http://www.no798.eu/notizie.php");
HttpResponse rp = null;
try {
rp = hc.execute(post);
} catch (IOException e) {
e.printStackTrace();
}
if (rp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
// Server is unavailable
}
try {
String str=EntityUtils.toString(rp.getEntity());
} catch (IOException e) {
e.printStackTrace();
}
}
});
trd.start();
How i can get out of Thread the EntityUtils String?
If a try java whant a Final one-element array String...
Create a Handler in your Activity or Fragment, and pass the result of the HTTP call to it.
In your Activity/Fragment:
private final static int HANDLER_FROM_HTTP = 1;
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
final int what = msg.what;
switch(what) {
case HANDLER_FROM_HTTP: {
Bundle b = msg.getDate();
if (b != null) {
String s = b.getString("result");
doSomething(s);
}
}
}
}
};
Then, in the run() method of your Thread above:
String str=EntityUtils.toString(rp.getEntity());
Message msg = pThreadHandler.obtainMessage(HANDLER_FROM_HTTP);
Bundle b = new Bundle();
b.putString("result", str);
msg.setData(b);
msg.sendToTarget();
This will allow you to execute doSomething() on the main UI thread to update a View, or perform some other action.

Put webpage text into a textview (Android)

I want to put a text from a webpage to a textview on Android 3.0. I have this code:
public class Biografie extends Activity {
private TextView outtext;
private String HTML;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_biografie);
outtext= (TextView) findViewById(R.id.textview1);
try {
getHTML();
} catch (Exception e) {
e.printStackTrace();
}
outtext.setText("" + HTML);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.biografie, menu);
return true;
}
private void getHTML() throws ClientProtocolException, IOException
{
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://artistone.appone.nl/api/biografie.php?dataid=998"); //URL!
HttpResponse response = httpClient.execute(httpGet, localContext);
String result = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = null;
while ((line = reader.readLine()) != null) {
result += line + "\n";
HTML = result;
}
}
}
My TextView returns "null" instead of the text from the page. Please help me to fix this. Thanks in regard.
Change your code to:
while ((line = reader.readLine()) != null) {
result += line + "\n";
}
HTML = result;
and try this:
outtext.setText(Html.fromHtml(HTML));
And instead of performing network action in main thread i will suggest you to do this in separate thread using AsyncTask
The problem is that you are getting NetworkOnMainThreadException
That is because you are downloading network content on the Main Thread (Activity's Thread).
Instead you need to use a background thread to download that content, or use AsynchTask.
A simple code that should fix this issue:
final Handler handler = new Handler();
Thread thread = new Thread() {
public void run() {
try {
getHTML();
handler.post(new Runnable() {
#Override
public void run() {
outtext.setText("" + HTML);
}
});
} catch (Exception e) {
e.printStackTrace();
handler.post(new Runnable() {
#Override
public void run() {
outtext.setText(e.toString());
}
}
}
};
thread.start(); // I forgot to start the thread. sorry !
Instead of :
try {
getHTML();
} catch (Exception e) {
e.printStackTrace();
}
outtext.setText("" + HTML);
Also take a look at this tutorial about android threads : Tutorial

Categories