Why connection.getResponseCode() fails outside of doInBackground()? - android

public String urltobody(String createdurl){
URL url = new URL (createdurl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int responseCode = connection.getResponseCode();//fails here
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream is = connection.getInputStream();
String content = convertInputStream(is, "UTF-8");
is.close();
return content;
}
}
The above function works if I call it inside of doInBackground but does not workin onPostExecute. I really need to call this function independent to pre, background, post prdocedure.
This is my class definition private class FetchTask extends AsyncTask < Void, Void, String>
Please let me know if you can help me with one of the below questions.
Do you know how I can call my function outside of doInbackground?
Do you know what happens when I call new FetchTask().execute()?
Any other solution?
Thank you in advance

The reason is that doInBackground is run in a background thread while onPreExectute onPostExecute are run in the UI-thread.
==> Url Connections should not be done from UI thread, (because it may freeze the UI while it is loading) that is why Android throws an NetworkOnMainThreadException whenever you try to do that.
==> This is the reason why you should establish network connections only asynchronously from the background thread not UI thread. That is why it only works in doInBackground.

You can try this code
private class FetchTask extends AsyncTask<Void, Void, Boolean>
instead of
private class FetchTask extenends AsyncTask < Void, Void, String>
May be solve your problem.
also for example for your understanding
private class ResponseLocDepts extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... params) {
URL url = new URL (createdurl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int responseCode = connection.getResponseCode();//fails here
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream is = connection.getInputStream();
String content = convertInputStream(is, "UTF-8");
is.close();
return true;
}
else
{
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
// somethings
}
}
String content should be globally diclare.
Please try it.

Related

publishProgress in Void cannot be applied to Strings in Asyntask?

I'm developing app to load pdf files in pdfView. I'm using Aynctask for this. I want to show the progress status in progress dialog.
Now the problem I'm facing is when I change AsyncTask<String, Void, InputStream> to AsyncTask<String, String, InputStream> percentage progress works well but pdf file not getting loaded to pdfView.
If I leave AsyncTask<String, Void, InputStream> as it is, I'm getting Error cannot resolve publishProgress, java.lang.Void in AsyncTask cannot be applied to java.lang.Strings. If I remove publishProgress my code works well pdf file is loading to pdfView but there is no actual progress update in progress dialog.
How to fix it? Please help me, I'm stuck here from many days.
here is my code for
PdfViewer.java
class RetrievePdfStream extends AsyncTask<String, Void, InputStream> {
#Override
protected InputStream doInBackground(String... strings) {
InputStream inputStream = null;
int count;
try {
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
int lenghtOfFile = urlConnection.getContentLength();
if (urlConnection.getResponseCode() == 200) {
inputStream = new BufferedInputStream(urlConnection.getInputStream());
}
byte data[] = new byte[1024];
long total = 0;
while ((count = inputStream.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress(""+(int)((total*100)/lenghtOfFile));
}
}
catch (IOException e) {
return null;
}
return inputStream;
}
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
protected void onPostExecute(InputStream inputStream) {
pdf.fromStream(inputStream).load();
pDialog.cancel();
}
}
Use <String, Integer, InputStream> and pass an Integer instead of a String:
publishProgress((int)((total*100)/lenghtOfFile))

Spying an AsyncTask doesn't work

I am testing an AsyncTask. I want to stub an HttpURLConnection to return my mocked object. This is how I do it (PackageDownloader represents an AsyncTask):
...
PackageDownloader packageDownloader = new PackageDownloader();
packageDownloader.setParameters(URL, downloadFolder, downloadProgressCallback);
PackageDownloader mPackageDownloader = spy(packageDownloader);
HttpURLConnection connectionMock = Mockito.mock(HttpURLConnection.class);
doReturn(0).when(connectionMock).getContentLength();
doReturn(connectionMock).when(mPackageDownloader).createConnection(Mockito.any(URL.class));
mPackageDownloader.execute();
mPackageDownloader.get();
This is PackageDownloader:
public HttpURLConnection createConnection(URL url) throws IOException {
HttpURLConnection connection;
connection = (HttpURLConnection) url.openConnection();
return connection;
}
#Override
protected DownloadResult doInBackground(Void... params) {
HttpURLConnection connection;
URL downloadUrl = new URL(downloadUrlString);
connection = createConnection(downloadUrl);
long totalBytes = connection.getContentLength();
...
Here, createConnection returns real, not mocked object, and I can't figure out why.
Well I have found a solution, though haven't found an explanation why it works so.
The reason nothing worked was that doInBackground method is async, I assume, so I had to call it directly via reflection, like so:
Method method = mPackageDownloader.getClass().getMethod("doInBackground", Void[].class);
method.invoke(mPackageDownloader, new Void[] {null});
You can use robolectric to test the asynctask rather than reflection. Following the ShadowApplication.runBackgroundTasks() should invoke the doInBackground() method.
#RunWith(RobolectricTestRunner.class)
public class AcknowledgeAppRemovedTaskTest {
#Test
public void execute_shouldOpenInputStreamOfConnection() throws IOException {
DownloadTask spy = spy(new DownloadTask());
HttpURLConnection connectionMock = mock(HttpURLConnection.class);
doReturn(connectionMock).when(spy).createConnection(any(URL.class));
spy.execute();
ShadowApplication.runBackgroundTasks();
verify(connectionMock).getInputStream();
}
}
class DownloadTask extends AsyncTask<Void, Void, Void> {}
public HttpURLConnection createConnection(URL url) throws IOException {
return (HttpURLConnection) url.openConnection();
}
#Override
protected Void doInBackground(Void... voids) {
try {
HttpURLConnection urlConnection = createConnection(new URL("https://www.google.com/"));
urlConnection.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
https://github.com/robolectric/robolectric/blob/master/robolectric/src/test/java/org/robolectric/shadows/ShadowAsyncTaskTest.java
https://groups.google.com/forum/#!topic/mockito/mqF21aqTi5g

Android Studio - Issues with using progress bar while AsyncTask loads website content

I am making a guessing app in Android Studio 2.2.3 for which I need to load some data from a website. I am using an AsyncTask class, which accepts the URL of the website as a String, and returns the data as String.
The problem is that the loading is extremely slow and so the app shows a blank white screen on the phone for about 15-20 seconds until (I presume) the whole thing is downloaded.
What I want to do is show an indeterminate progress bar (I think that's what the rotating circle is called) until the app loads the data.
For this, I tried to pass in the AsyncTask, and then made the progressbar view visible in the onPreExecute() and invisible again in the onPostExecute().
But this didn't work out and it still showed the same white screen.
Here's my AsyncTask:
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pb.setVisibility(ProgressBar.VISIBLE);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
pb.setVisibility(ProgressBar.INVISIBLE);
}
#Override
protected String doInBackground(String... urls) {
String result = "";
URL url;
HttpURLConnection urlConnection;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
int data = isr.read();
while (data != -1) {
char current = (char) data;
result += current;
data = isr.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
}
//if try fails
return null;
}
}
And this is when I call it in the onCreate()
DownloadTask downloadTask = new DownloadTask();
String result;
try {
String websiteUrl = "http://www.india-forums.com/celebrity/bollywood/";
result = downloadTask.execute(websiteUrl).get();
I read somewhere that the get() blocks the main UI thread, but if I remove it, I get an Incompatible types error, so couldn't still resolve it...
What am I missing/doing wrong?
Any help would be appreciated!

Memory Leak with AsyncTask

i appear to have a memory leak with the following asyncTask, what possible cause are there?
/**
* Async task class to get json by making HTTP call
* */
public class PostLocation extends AsyncTask<String, Void, String>
{
#Override
protected void onPreExecute()
{
}
#Override
protected String doInBackground(String... params)
{
try
{
String response = "";
URL url = new URL(BASE_URL + "receiveLocation.php");
myConnection = (HttpURLConnection) url.openConnection();
myConnection.setRequestMethod("POST");
myConnection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(myConnection.getOutputStream());
wr.writeBytes(params[0]);
int responseCode = myConnection.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK)
{
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(myConnection.getInputStream()));
while ((line = br.readLine()) != null)
{
response += line;
}
}
else
{
return response = "";
}
return response;
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return "false";
}
}
#Override
protected void onPostExecute(String result)
{
if(result.equals("success"))
{
myConnection.disconnect();
}
}
}
this is simply posting some data to my server. What could be causing memory leaks, note this task is called in the background from a broadcast receiver using goAsync
The problem here is in your class structure.
A nested class should be declared static whenever possible, otherwise it will keep the enclosing class in memory, leading to memory leaks.
Change:
public class PostLocation extends AsyncTask<String, Void, String>
to:
public static class PostLocation extends AsyncTask<String, Void, String>
Here is an exercise:
Put a field called boolean test in your BroadcastReceiver class
Now in your nested class, try to access this field, e.g. test == true
If the nested class is not static, you will be able to access the field. This is because the instance of the class keeps the reference to the enclosing class. But if you make PostLocation class static, the field will not be available.
Yes you need to close the inputstream first and close httpconnection next. As per javadoc.
Each HttpURLConnection instance is used to make a single request but
the underlying network connection to the HTTP server may be
transparently shared by other instances. Calling the close() methods
on the InputStream or OutputStream of an HttpURLConnection after a
request may free network resources associated with this instance but
has no effect on any shared persistent connection. Calling the
disconnect() method may close the underlying socket if a persistent
connection is otherwise idle at that time.
Source

General AsyncTask, use one AsyncTask in multiple contexts

I'm using AsyncTask and all the examples I found about an AsyncTask is inside an activity.
I'm trying to make an application with a lot of activity and some must download a HTML page. I don't really want to copy-paste the same code all the time in every activity. I find this to be dirty.
So I need to do it as a special class Async HttpGet and pass the function with an argument. I will execute after the doinbackground (different for every activity).
Is this possible or do I need to copy-paste my code in every activity and change the do in background to do what I need after downloading the HTML page?
Here's an AsyncTask that will download data from a url and update the calling activity.
Make sure your calling activity implements the interface DownloadDataTask.DownloadCompleteHandler and that it passes itself as parameter to the DownloadDataTask constructor.
public class DownloadDataTask extends AsyncTask<String, Integer, String> {
public interface DownloadCompleteHandler
{
public void handleDownloadComplete(String result);
}
private DownloadCompleteHandler handler;
private String url;
public DownloadDataTask(DownloadCompleteHandler handler, String url) {
this.handler = handler;
this.url = url;
}
/* AsyncTask methods */
#Override
protected String[] doInBackground(String... empty) {
return downloadData(url);
}
#Override
protected void onPostExecute(String result) {
handler.handleDownloadComplete(result);
}
/* Downloading Data */
private String downloadData(String urlStr) {
InputStream is = null;
String result = new String();
try {
is = getInputStream(urlStr);
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result += inputLine;
} catch (MalformedURLException ex) {
return "Malformed URL: " + ex.getMessage();
} catch (SocketTimeoutException ex) {
return "Connection timed out";
} catch (IOException ex) {
return "IOException: " + ex.getMessage();
}
finally {
if (is != null)
is.close();
}
return result;
}
private InputStream getInputStream(String urlStr) throws IOException
{
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(7000);
conn.setConnectTimeout(7000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
return conn.getInputStream();
}
}
Just create a class that extends AsyncTask that you can reuse.
public abstract class MyAsyncTask extends AsyncTask<Void, Void, String> {
private final String url;
public MyAsyncTask(String url){
this.url = url;
}
#Override
protected String doInBackground(Void... params){
// get data from url.
return null;
}
}
And then to call it, just create an instance of that class.
new MyAsyncTask("http://www.google.com"){
public void onPostExecute(String result){
// update your views.
}
}.execute();
Well what you can do is create an listener for AsyncTask completion, which listens when your AsyncTask is completed and return you the data. I had created an example to execute database queries in background thread and then returning the data to the Activity. Just check it and you can create similar AsyncTask for your problem.
UPDATE:-
Also you can use BroadCastReceiver as a Listener when your AsyncTask is completed and return the value.
Interface is another option for creating a Listener for AsyncTask.
Here is a demo from my github

Categories

Resources