I'm trying to use AsyncTask and BufferedReader to read the line shown in the http with the following code.
private class DownloadFilesTask extends AsyncTask <Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
String request_url = "http://www.ryanheise.com/sarcastic.cgi";
try {
URL url = new URL(request_url);
try {
URLConnection conn = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
try {
String joke = in.readLine();
Log.d("Joke -- ", joke);
return joke;
} finally {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
Log.d("IOE", " ----------- IOE");
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.d("MURL", " ----------- MURL");
}
return "unable to get joke";
}
#Override
protected void onProgressUpdate(Integer... progress) {
}
#Override
protected void onPostExecute(String result) {
mJoke_tv.setText(result);
Log.d("onPost", result);
}
}
and it runs with no exception but returns an unexpected result.
the log.d("joke---" , joke) shows:
"!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">"
which I have no idea why.
the logcat shows:
D/JokeĀ --: !DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
can anyone help me out of it please?
many thanks.
Related
Every tutorial I find seems to use AsyncTask (depreciated) instead of ExecutorService. I took a java course on Udemy and they used AsyncTask for everything as well. Here is one class I'm working with:
public class FetchURL extends AsyncTask<String, Void, String> {
Context mContext;
String directionMode = "driving";
public FetchURL(Context mContext) {
this.mContext = mContext;
}
#Override
protected String doInBackground(String... strings) {
// For storing data from web service
String data = "";
directionMode = strings[1];
try {
// Fetching the data from web service
data = downloadUrl(strings[0]);
Log.d("mylog", "Background task data " + data.toString());
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
PointsParser parserTask = new PointsParser(mContext, directionMode);
// Invokes the thread for parsing the JSON data
parserTask.execute(s);
}
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
Log.d("mylog", "Downloaded URL: " + data.toString());
br.close();
} catch (Exception e) {
Log.d("mylog", "Exception downloading URL: " + e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
}
and I'd really like to use ExecutorService like here instead of AsyncTask. I'm beating my head against the wall and I can't seem to get the proper arguments in and this thing working.
Replace your AsyncTask with a Runnable:
public class FetchUrl implements Runnable {
public interface Callback {
void onSuccess(String data);
void onFailure(Exception e);
}
private String url;
private WeakReference<Callback> callbackWeakReference;
public FetchUrl(String url, Callback callback) {
this.url = url;
this.callbackWeakReference = new WeakReference<>(callback);
}
#Override
public void run() {
try {
String data = downloadUrl(url);
Callback callback = callbackWeakReference.get();
if (callback != null) {
callback.onSuccess(data);
}
} catch (Exception e) {
Callback callback = callbackWeakReference.get();
if (callback != null) {
callback.onFailure(e);
}
}
}
... // include your downloadUrl function
}
Then create and submit it to the ExecutorService:
FetchUrl.Callback callback = new FetchUrl.Callback() {
#Override
public void onSuccess(String data) {
// handle your data
}
#Override
public void onFailure(Exception e) {
// handle the exception
}
};
Runnable job = new FetchUrl(url, callback);
ExecutorService executorService = Executors.newFixedThreadPool(4);
executorService.submit(job);
Notice I used a WeakReference<Callback>, because code in your callback is holding a reference to Context and would cause Context leaks.
The submit() function returns a Future to control your submitted job. It's handy if you want to cancel the job or want to wait for its completion (blocking the current thread). The latter usecase would perhaps favor using Callable<Result> instead of Runnable, because the calling thread can handle the exception and there would be no use for a callback making your code more concise.
Also don't forget to call shutdown() on your ExecutorService when you no longer need it.
I've an AsyncTask with below code
private void getJSON(final String urlWebService) {
class GetJSON extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExcute();
}
#Override
protected String doInBackground(Void... voids) {
try {
URL url = new URL(urlWebService);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append(json);
}
return sb.toString().trim();
} catch (Exception e) {
Log.i("BG Exception", e.getMessage());
return "";
}
}
}
new GetJSON().execute();
But, unfortunately it returns error like below
java.lang.VerifyError: Verifier rejected class net.simplifiedlearning.androidjsonparsing.MainActivity$100000000$GetJSON due to bad method void net.simplifiedlearning.androidjsonparsing.MainActivity$100000000$GetJSON.<init>(net.simplifiedlearning.androidjsonparsing.MainActivity, java.lang.String) (declaration of 'net.simplifiedlearning.androidjsonparsing.MainActivity$100000000$GetJSON' appears in /data/app/net.simplifiedlearning.androidjsonparsing-1/base.apk)
05-25 11:04:26.146 29104 29104 E AndroidRuntime at net.simplifiedlearning.androidjsonparsing.MainActivity.getJSON(MainActivity.java:76)
I've found it's solution.
The error says
Verifier rejected AsyncTask due to bad void
The AsyncTask is in a void method. And that was doing the problem. Though, I don't know why?
When I've removed the getJSON() void which was surrounding AsyncTask everything became fine and worked expectedly.
I am trying to return the content of a text file on localhost (wamp server) as a string. I can read the text file but I cannot return a string because the function run of Runnable is a void. I'm working on Android Studio (that's why I'm using thread).
public String serverToString()
{
String str;
Thread t = new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://myIP/test.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
str = in.readLine();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Throwable th) {
th.printStackTrace();
}
}
});
t.start();
return str;
}
Advancing the the Cricket answer, I usually create an AsyncTask and inside it I define a callback interface.
The activity executing this task should implements this interface.
As an example of part of the code:
public class TeamUpdateTask extends AsyncTask, Object, TeamUpdateResponse> {
private TeamUpdateTaskCallback mListener;
#Override
public void onPostExecute (TeamUpdateResponse result) {
if (exception == null) {
mListener.OnTeamUpdateCompleted(result);
} else {
processException();
}
}
public void setListener (TeamUpdateTaskCallback listener) {
mListener = listener;
}
public interface TeamUpdateTaskCallback {
void OnTeamUpdateCompleted (TeamUpdateResponse response);
}
}
Hope it helps.
Generally, Volley library would be preferred over raw Thread. Or AsyncTask
but I cannot return a string because the function run of Runnable is a void
You can pass the result to a new method, though.
Define an interface
public interface ServerResponse {
void onResponse(String msg);
}
Add a parameter
public void serverToString(final ServerResponse callback)
{
String str;
Thread t = new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://myIP/test.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
callback.onResponse(in.readLine()); // This is the 'return' now
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Throwable th) {
th.printStackTrace();
}
}
});
t.start();
}
And instead of this
String response = serverToString();
Do this
serverToString(new ServerResponse() {
#Override
public void onResponse(String response) {
// handle message
}
});
I am attempting to pass a string I got in an Asynchronous task class back in to my main activity, but when I pass the string result (which I know isn't null because logging the string right before passing it to the interface outputs what it should), I get a nullPointerException that says I can't pass a null object to the interface method.
Here is the AsyncTask class,
public class APICalls extends AsyncTask<String,Void, String> {
public AsyncResponse delegate;
protected String doInBackground(String... zipcodes){
String zipcode = zipcodes[0];
String apikey = "6562c36e87ba41f6bc887104d1e82eb8";
String baseURL = "https://congress.api.sunlightfoundation.com";
String zipCodeAddition = "/legislators/locate?apikey="+apikey + "&zip=" + zipcode;
String url = baseURL + zipCodeAddition;
String results = "";
URL apiurl = null;
try {
apiurl = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpsURLConnection urlConnection = null;
try {
urlConnection = (HttpsURLConnection) apiurl.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
int data = in.read();
while(data != -1){
results += String.valueOf((char) data);
data = in.read();
}
in.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
urlConnection.disconnect();
}
return results;
}
protected void onPostExecute(String result){
String results = result;
try {
delegate.processFinish(results);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The error occurs in the line delegate.processFinish(results);. When I log the results string it is not null. The interface is:
public interface AsyncResponse {
void processFinish(String output) throws IOException;
}
Then in the main activity I implement the interface and have the method:
public void processFinish(String output) throws IOException {
Log.v("++++++++", output);
}
You get NPE not because output is null, but because delegate is. You never initialize it.
This question already has answers here:
Android AsyncTask don't return correct Result
(3 answers)
Closed 8 years ago.
in this below code i want to return value from AsyncTask with using an Interface. but i get wrong value and i can not return correct value from onPostExecute.
i'm developed this link tutorials with my code. i can not use correctly with that.
Interface:
public interface AsyncResponse {
void processFinish(String output);
}
Ksoap Main class:
public class WSDLHelper implements AsyncResponse{
public SoapObject request;
private String Mainresult;
public String call(SoapObject rq){
ProcessTask p =new ProcessTask(rq);
String tmp = String.valueOf(p.execute());
p.delegate = this;
return Mainresult;
}
#Override
public void processFinish(String output) {
this.Mainresult = output;
}
}
class ProcessTask extends AsyncTask<Void, Void, Void > {
public AsyncResponse delegate=null;
SoapObject req1;
private String result;
public ProcessTask(SoapObject rq) {
req1 = rq;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(this.req1);
AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
transport.debug = true;
try {
transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
this.result = envelope.getResponse().toString();
} catch (IOException ex) {
Log.e("" , ex.getMessage());
} catch (XmlPullParserException ex) {
Log.e("" , ex.getMessage());
}
if (result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
try {
throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
} catch (TException e) {
e.printStackTrace();
}
}
Log.e("------------++++++++++++++++-----------", this.result);
return null;
}
protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
delegate.processFinish(this.result);
}
}
please help me to resolve this problem
That can't work. You are creating and executing the AsyncTask (asynchronously!) and then call return Mainresult (synchronously!) when it hasn't received the result yet. The solution is to remove the redundant class WSDLHelper and access ProcessTask directly
Beside that, you're using AsyncTask incorrectly (saving the result in a class variable instead of passing it as a parameter). Here's the full version:
public class ProcessTask extends AsyncTask<Void, Void, String> {
public AsyncResponse delegate=null;
SoapObject req1;
public ProcessTask(SoapObject rq, AsyncResponse delegate) {
req1 = rq;
this.delegate = delegate;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(this.req1);
AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
transport.debug = true;
String result = null;
try {
transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
result = envelope.getResponse().toString();
} catch (IOException ex) {
Log.e("" , ex.getMessage());
} catch (XmlPullParserException ex) {
Log.e("" , ex.getMessage());
}
if (result != null && result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
try {
throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
} catch (TException e) {
e.printStackTrace();
}
}
Log.e("------------++++++++++++++++-----------", result);
return result;
}
protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
delegate.processFinish(result);
}
}
Now you would execute ProcessTask from outside like this, which will make sure you receive the result asynchronously:
new ProcessTask(rq, new AsyncResponse() {
#Override
public void processFinish(String output) {
// do whatever you want with the result
}
}).execute();
Your result will always be null, because you return null in the doInBackground() method. The value you return in doInBackground() will be passed to onPostExecute(). Change your AsyncTask<Void, Void, Void> to AsyncTask<Void, Void, String>, and return the result. This will call onPostExecute(String result) with the correct result.
Perhaps this link might help you a bit: http://bon-app-etit.blogspot.be/2012/12/using-asynctask.html