Using Android AsyncTask to download html file - android

i just started with android and i'm working on a simple app that should download contents of a html file. I'm using AsyncTask as suggested, but i'm encountering one problem. In the following code (i followed a tutorial code), i get tv cannot be resolved for the onPostExecute method. How to access the downloaded file? Thank You:
public class FlashResults extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
protected class DownloadPage extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String responseStr = null;
try {
for (String url : urls) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(get);
HttpEntity httpEntity = httpResponse.getEntity();
responseStr = EntityUtils.toString(httpEntity);
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return responseStr;
}
protected void onPostExecute(String result) {
tv.setText(result);
}
}
public void readWebpage(View v) {
DownloadPage task = new DownloadPage();
task.execute(new String[] { "http://seznam.cz" });
}
}

All of the other answers suggested so far will work. However, I would add in a couple of other notes:
if you are only accessing the TextView tv inside this onCreate and the DownloadPage acitivity, you can limit access to tv by giving it directly to the DownloadPage's constructor
for something as useful as a DownloadPage AsyncTask, i usually remove it from being an inner class of any activity and instead put it in a public class called "Utils" that can be used by many other activities as needed. (modularity in code)
if you are going to use an inner class (perfectly legal), it's always good practice to make it private and static for what you're doing.
Something like this:
public class FlashResults extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
public void readWebpage(View v) {
DownloadPage task = new DownloadPage(tv);
task.execute(new String[] { "http://seznam.cz" });
}
private static class DownloadPage extends AsyncTask<String, Void, String> {
private TextView textView;
public DownloadPage(TextView tv){
textView = tv;
}
protected String doInBackground(String... urls) {
String responseStr = null;
try {
for (String url : urls) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(get);
HttpEntity httpEntity = httpResponse.getEntity();
responseStr = EntityUtils.toString(httpEntity);
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return responseStr;
}
protected void onPostExecute(String result) {
if (textView != null) {
textView.setText(result);
}
}
}
}
}

One approach is to do as the other answers suggest and make tv instance level. Alternatively you can make a TextView field within your AsyncTask and pass a reference into the constructor:
...
public void readWebpage(TextView v) {
DownloadPage task = new DownloadPage(v);
task.execute(new String[] { "http://seznam.cz" });
}
...
protected class DownloadPage extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
...
}
TextView tv = null;
public DownloadPage(TextView tv){
this.tv = tv;
}
...
}

If you want a variable to be accessible outside of a method, you need to declare it outside a method. This is a basic programming concept called scope.
Change your code to look like this:
public class FlashResults extends Activity {
private TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
and it will be available to anything inside FlashResults.

Try making the text view class-level variable.
private TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
The other option would be declaring your AsyncTask anonymous, declaring the TextView as final in the same method body as your declaration of the task.
Cheers

You have to make tv a feild to make it accessible from a subclass.
public class FlashResults extends Activity {
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TextView(this);
setContentView(tv);
readWebpage(tv);
}
protected class DownloadPage extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String responseStr = null;
try {
for (String url : urls) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(get);
HttpEntity httpEntity = httpResponse.getEntity();
responseStr = EntityUtils.toString(httpEntity);
}
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return responseStr;
}
protected void onPostExecute(String result) {
tv.setText(result);
}
}
public void readWebpage(View v) {
DownloadPage task = new DownloadPage();
task.execute(new String[] { "http://seznam.cz" });
}
}

Related

getApplicationContext() method cannot be resolved, LoginActivity.this is not an enclosing class

In the ProgressDialog initialization it is showing that LoginActivity.this is not an enclosing class.
In onPostExecute() method Toast is not getting executed and getApplicationContext() method cannot be resolved.
public class LoginActivity extends AppCompatActivity {
EditText et1,et2;
Button b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
et1=(EditText)findViewById(R.id.editText5);
et2=(EditText)findViewById(R.id.editText6);
b=(Button)findViewById(R.id.button2);
}
public void login(View view)
{
new BackgroundTask().execute(et1.getText().toString(),et2.getText().toString());
Toast.makeText(this,"Button",Toast.LENGTH_LONG).show();
}
}
class Background extends AsyncTask<String, Integer, Integer>
{
ProgressDialog progressDialog=new ProgressDialog(LoginActivity.this);;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Processing");
progressDialog.setTitle("Title");
progressDialog.show();
}
int check_point =0;
String resp="";
#Override
protected Integer doInBackground(String... params) {
try {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://192.168.1.6/login.php");
HttpResponse response = client.execute(post);
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String s;
while ((s = reader.readLine()) != null) {
resp=resp+s;
}
}
catch (Exception e)
{
System.out.print(e);
}
return check_point;
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
progressDialog.dismiss();
Toast.makeText(getApplicationContext(),"ACtivity",Toast.LENGTH_LONG).show();
}
}
The class Background is not an inner class. Its outside of the scope of the LoginActivity.
Thats why you're getting that error. Try moving it as an inner class.
classs ParentClass{
//some fields, methods whatevenr
class InnerClass{
// this is inner
}
}
class OutSideScope{
// this is outside of the scope of the Parent Class
}
Happy coding ;)

Return JSON String from AsyncTask Android

Normally I create classes for every web service call that extends with the AsyncTask and it's so hard to maintain the code. So I think to create the One class and get the OUTPUT Json string according to the parameters.
how do I return the JSON string?
UPDATE
Here what I tried
public class WebCallController extends AsyncTask<Void,Void,String>
{
String PassPeram = "";
JSONStringer JSonRequestString;
String URL;
String JSonResponseString;
public WebCallController(String PerameterPass, JSONStringer JSonRequestString, String URL) {
PassPeram = PerameterPass;
this.JSonRequestString = JSonRequestString;
this.URL = URL;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(URL);
post.setHeader("Content-type", "application/json");
try {
StringEntity entity = new StringEntity(JSonRequestString.toString());
post.setEntity(entity);
}
catch (Exception Ex)
{
}
try {
HttpResponse response = client.execute(post);
StatusLine status = response.getStatusLine();
int statusCode = status.getStatusCode();
if(statusCode == 400)
{
Log.d("Error", "bad request");
}
else if(statusCode == 505)
{
Log.d("Error","Internal server error");
}
else
{
InputStream jsonStream = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(jsonStream));
StringBuilder builder = new StringBuilder();
String line;
while((line = reader.readLine()) != null)
{
builder.append(line);
}
JSonResponseString = builder.toString();
}
}
catch (IOException Ex)
{
}
return JSonResponseString;
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
}
}
this may be what you are looking for(get string as result and parse it to json):
YourAsycTask yat=new YourAsycTask();
yat.execute();
String result=yat.get().toString();
I am assuming that you need to write one AsyncTask which can be reusable for every webservice call. You can do something like below example ,
Step-1: Create a abstract class
public abstract class HttpHandler {
public abstract HttpUriRequest getHttpRequestMethod();
public abstract void onResponse(String result);
public void execute(){
new AsyncHttpTask(this).execute();
}
}
2. Sterp-2: Write your AsyncTask code
public class AsyncHttpTask extends AsyncTask<String, Void, String>{
private HttpHandler httpHandler;
public AsyncHttpTask(HttpHandler httpHandler){
this.httpHandler = httpHandler;
}
#Override
protected String doInBackground(String... arg0) {
//do your task and return the result
String result = "";
return result;
}
#Override
protected void onPostExecute(String result) {
httpHandler.onResponse(result); // set it to the onResponse()
}
}
Step-3: Write your Activity code
public class MainActivity extends Activity implements OnClickListener {
private Button btnRequest;
private EditText etResponse;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnRequest = (Button) findViewById(R.id.btnRequest);
etResponse = (EditText) findViewById(R.id.etRespose);
//check isConnected()...code is on github
btnRequest.setOnClickListener(this);
}
#Override
public void onClick(View v) {
new HttpHandler() {
#Override
public HttpUriRequest getHttpRequestMethod() {
return new HttpGet("http://hmkcode.com/examples/index.php");
// return new HttpPost(url)
}
#Override
public void onResponse(String result) {
Toast.makeText(getBaseContext(), "Received!", Toast.LENGTH_LONG).show();
etResponse.setText(result);
}
}.execute();
}
// public boolean isConnected(){}
}
reference
http://hmkcode.com/android-cleaner-http-asynctask/
https://github.com/hmkcode/Android/tree/master/android-clean-http-async-task
Try out below code and put it in separate class from where it returns json string to your activity.
Only pass your url to this method and get the response in a string formate.
public static final String GetConnectionInputStream(String strUrl) {
String line = null;
String response = null;
try {
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is
// established.
// The default value is zero, that means the timeout is not used.
HttpConnectionParams.setConnectionTimeout(httpParameters, 30000);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
HttpConnectionParams.setSoTimeout(httpParameters, 30000);
// This is the default apacheconnection.
HttpClient mHttpClient = new DefaultHttpClient(httpParameters);
// Pathe of serverside
HttpGet mHttpGet = new HttpGet(strUrl);
// get the valu from the saerverside as response.
HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet);
HttpEntity mHttpEntity = mHttpResponse.getEntity();
try {
// convert response in to the string.
if (mHttpEntity.getContent() != null) {
BufferedReader mBufferedReader = new BufferedReader(
new InputStreamReader(mHttpEntity.getContent(),
HTTP.UTF_8), 8);
StringBuilder mStringBuilder = new StringBuilder();
while ((line = mBufferedReader.readLine()) != null) {
mStringBuilder.append(line + "\n");
}
response = mStringBuilder.toString();
// mInputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return response;
}
Change your doInBackground method as below:
private class GetParsedResponse extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
String response=null;
response=GetConnectionInputStream(URL);
return response;
}
#Override
protected void onPostExecute(String result) {
//your response parsing code.
}
}
private class MyAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
return "Executed";
}
#Override
protected String onPostExecute(String result) {
return "json String";
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}

using a String[] outside a method

I am trying to use the String[] mtake outside the onPostExecute(String) method. It gives me proper value inside the function but nothing in onCreate() method and simple crashes the app. Any help is appreciated. Thanks in advance. I have tried declaring it public static globally and inside the class. Static doesn't work either.
#SuppressLint({ "CutPasteId", "SimpleDateFormat", "SdCardPath" })
public class MainActivity extends Activity implements View.OnClickListener {
public String[] mtake;
public class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#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;
}
}
catch (Exception e) {
e.printStackTrace();
}
}
return response.toString();
}
public void onPostExecute (String result) {
mtake = result.split("#");
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Handler handIn = new Handler();
final Timer T2 = new Timer();
T2.scheduleAtFixedRate(new TimerTask() {
public void run() {
handIn.post(new Runnable() {
public void run() {
txt = (TextView) findViewById(R.id.Text);
txt.setText(mtake[0]);
}
});
}
},0, 20000);
}
You aren't instantiating the mTake array with anything. In your onPostExecute method, you're calling mTake.equals(result.split("#")) which returns a boolean, not a String[]. Did you mean mTake = result.split("#")?

android:how to get tag from html

I'm trying to get specific tag from one web site.
I can read the HTML but can't get the specific tag.
Is there any way to do this task?
I was searching in other threads but I could not find the solution.
Thanks in advance.
Here is the code.
public class MainActivity extends Activity {
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.text);
DownloadTask task = new DownloadTask();
task.execute("http://zodia.bg/sign/aries");
}
private class DownloadTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... urls) {
HttpResponse response = null;
HttpGet httpGet = null;
HttpClient mHttpClient = null;
String s = "";
try {
if(mHttpClient == null){
mHttpClient = new DefaultHttpClient();
}
httpGet = new HttpGet(urls[0]);
response = mHttpClient.execute(httpGet);
s = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
#Override
protected void onPostExecute(String result){
text.setText(result);
}
}
}
You can either use a DOM traversal with something like jsoup or you can manually use String manipulation to find what you need and parse it out (substring() and indexOf(), etc.)

show an error message when can not requested URL in android

I have this code to request an URL and show the result on the screen by a TextView. this is my code:
public class AsyncronoustaskAndroidExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asyncronoustask_android_example);
final Button GetServerData = (Button) findViewById(R.id.GetServerData);
GetServerData.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String serverURL = "http://androidexample.com/media/webservice/getPage.php";
new LongOperation().execute(serverURL);
}
});
}
private class LongOperation extends AsyncTask<String, Void, Void> {
private final HttpClient Client = new DefaultHttpClient();
private String Content;
private String Error = null;
private ProgressDialog Dialog = new ProgressDialog(AsyncronoustaskAndroidExample.this);
TextView uiUpdate = (TextView) findViewById(R.id.output);
protected void onPreExecute() {
uiUpdate.setText("Output : ");
}
protected Void doInBackground(String... urls) {
try {
// Server url call by GET method
HttpGet httpget = new HttpGet(urls[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
Content = Client.execute(httpget, responseHandler);
} catch (ClientProtocolException e) {
Error = e.getMessage();
cancel(true);
} catch (IOException e) {
Error = e.getMessage();
cancel(true);
}
return null;
}
protected void onPostExecute(Void unused) {
// NOTE: You can call UI Element here.
if (Error != null) {
uiUpdate.setText("Output : "+Error);
} else {
uiUpdate.setText("Output : "+Content);
}
}
}
}
But when the URL is invalid, my program stop, I tried to show an error message but I can't. please help me!
thank so much.
Please check your log cat. Mostly you must be getting an IllegalStateException. If it is the case you have got to catch that too.
If you want to check your url is valid or invalid you need to use URL. Here's the example.
URL url;
try {
url = new URL(urls[0]);
HttpGet httpGet = new HttpGet(url.toString());
} catch (MalformedURLException e1) {
e1.printStackTrace();
}

Categories

Resources