Can't read directly from URL using AsynTask - java

I am trying to develop an application that reads jokes from a URL. I am using an AsyncTask to read from URL and then put the string to a textView. But I can't figure out why it isn't working.
Here is my code:
public class MainActivity extends AppCompatActivity {
private Button oneJokeBtn, threeJokesBtn;
private final static String ERROR_TAG = "Download Error";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Capturing our buttons from the view
oneJokeBtn = findViewById(R.id.joke_1);
threeJokesBtn = findViewById(R.id.joke_3);
// Register the onClick listener
oneJokeBtn.setOnClickListener(buttonHandler);
threeJokesBtn.setOnClickListener(buttonHandler);
// Declaring the Spinner
Spinner spinner = findViewById(R.id.spinner);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.length_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
// Spinner onItemSelector implemented in the OnCreate Method
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (position){
case 0:
Toast.makeText(parent.getContext(), R.string.short_toast, Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(parent.getContext(), R.string.medium_toast, Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(parent.getContext(), R.string.long_toast, Toast.LENGTH_SHORT).show();
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/** AsyncTask that reads one joke directly from the URL and adds it to the textView */
private class Download1JokeAsyncTask extends AsyncTask <Void, Void, String> {
private ProgressDialog progressDialog;
private String mResponse = "";
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage(getString(R.string.progress_msg));
progressDialog.setIndeterminate(true);
progressDialog.show();
}
#Override
protected String doInBackground(Void... voids) {
String joke = null;
try {
// Open a connection to the web service
URL url = new URL( "http://www-staff.it.uts.edu.au/~rheise/sarcastic.cgi" );
URLConnection conn = url.openConnection();
// Obtain the input stream
BufferedReader in = new BufferedReader( new InputStreamReader(conn.getInputStream()));
// The joke is a one liner, so just read one line.
joke = in.readLine();
// Close the connection
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e(ERROR_TAG, "Exception: ", e);
mResponse = getString(R.string.fail_msg);
} catch (IOException e) {
e.printStackTrace();
Log.e(ERROR_TAG, "Exception: ", e);
mResponse = getString(R.string.fail_msg);
}
return joke;
}
#Override
protected void onPostExecute(String joke) {
TextView tv = findViewById(R.id.tv_joke);
if (joke == null) {
tv.setText(R.string.fail_msg);
}
else {
tv.setText(joke);
}
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
/** AsyncTask that reads three jokes directly from the URL and adds it to the textView */
private class Download3JokeAsyncTask extends AsyncTask<Void, Integer, String[]> {
private ProgressDialog mProgressDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setProgress(0);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setCancelable(true);
mProgressDialog.setMessage(getString(R.string.three_jokes_btn));
mProgressDialog.show();
}
#Override
protected String[] doInBackground(Void... voids) {
int count = 2;
for (int i = 0; i < 2; i++){
try {
URL url = new URL("http://www.oracle.com/");
URLConnection conn = url.openConnection();
// Obtain the input stream
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// The joke is a one liner, so just read one line.
String joke;
while ((joke = in.readLine()) != null) {
System.out.println(joke);
}
// Close the connection
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e(ERROR_TAG, "Exception: ", e);
} catch (IOException e) {
e.printStackTrace();
Log.e(ERROR_TAG, "Exception: ", e);
}
publishProgress((int) ((i / (float) count) * 100));
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
setProgress(0);
}
#Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
}
}
/** onClickListener that gets the id of the button pressed and download jokes accordingly */
OnClickListener buttonHandler = new OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.joke_1:
new Download1JokeAsyncTask().execute();
break;
case R.id.joke_3:
new Download3JokeAsyncTask().execute();
break;
}
}
};
The AsyncTask is called Download1JokeAsyncTask, it is supposed to read from URL and then put it into a text view. and I've put an error message to appear in the text view if the joke (the string where the joke is stored) is null.
And always the text view says that it failed to download a message.
Please help.

I went to your joke page and inspecting the source (in Firefox) and I found this:
<html>
<head>
<link rel="alternate stylesheet" type="text/css" href="resource://content-accessible/plaintext.css" title="Wrap Long Lines">
</head>
<body>
<pre>I'm really good at stuff until people watch me do that stuff.</pre>
</body>
</html>
So you could save the whole output as a String and then use this:
string.substring(string.indexOf("<pre>"), string.indexOf("</pre>");
string.substring(4);
Basically you are downloading only the first line of the page which would be the content declaration.
Instead you need to download the sixth line and remove the pre tags.
Good Luck!

Related

ArrayList doesn't display value outside of method where the data storing happens

I have this class where it process XML and store it inside an ArrayList<FeedItem>. I can display the array content in the method where I store the data but when I try to display the array in another method it did not pass the if checking indicating that the ArrayList is empty. Because of this, I can't create a ListView because it'll return the same error. I hope someone can briefly explain to me what is wrong.
ReadRSS.java
public class ReadRSS extends AsyncTask<Void, Void, Void> {
//Initialize progress dialog
Context context;
String address;
ProgressDialog progressDialog;
XmlPullParserFactory xmlPullParserFactory;
volatile boolean parsingComplete = true;
ArrayList<FeedItem> feedItems;
ListView listView;
public ReadRSS(Context context, ListView listView, String retrieveAddress) {
//Create a new progress dialog
this.listView = listView;
this.address = retrieveAddress;
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading....");
}
// Runs in UI before background thread is called
#Override
protected void onPreExecute() {
//Display progress dialog
progressDialog.show();
super.onPreExecute();
}
// This is run in a background thread
#Override
protected Void doInBackground(Void... voids) {
fetchXML();
return null;
}
// This is called from background thread but runs in UI
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(Void aVoid) {
//Dismiss progress dialog
super.onPostExecute(aVoid);
progressDialog.dismiss();
/*if(listView != null) {
CustomAdapter customAdapter = new CustomAdapter(context, R.layout.activity_listview, feedItems);
listView.setAdapter(customAdapter);
}*/
if(feedItems != null){
//Gives error
for(int i = 0; i < feedItems.size(); i++) {
Log.d("Title", feedItems.get(i).getTitle());
Log.d("Date", feedItems.get(i).getPubDate());
}
}
}
//New Build
public void parseXMLAndStoreIt(XmlPullParser myParser) {
int event;
String text;
String title = null;
String date = null;
feedItems = new ArrayList<FeedItem>();
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String tagName = myParser.getName();
switch (event){
case XmlPullParser.START_TAG:
if(tagName.equalsIgnoreCase("item")){
int eventChild = myParser.next();
//int innerLoop = 1;
String tagNameChild = "";
while(eventChild != XmlPullParser.END_DOCUMENT){
if(eventChild == XmlPullParser.START_TAG){
tagNameChild = myParser.getName();
// Output Test
//Log.d("Tag ", tagNameChild);
}
else if (eventChild == XmlPullParser.TEXT){
text = myParser.getText();
// Output Test
//Log.d("Test ", text);
if(tagNameChild.equalsIgnoreCase("title")){
title = text;
// Output Test
//Log.d("Title ", myParser.getText());
}
else if(tagNameChild.equalsIgnoreCase("pubDate")){
date = text;
// Output Test
//Log.d("PubDate ", myParser.getText());
}
}
else if (eventChild == XmlPullParser.END_TAG){
if(myParser.getName().equalsIgnoreCase("item")){
feedItems.add(new FeedItem(title,date));
// Output Test
//Log.d("Test ", title);
}
tagNameChild = "";
}
eventChild = myParser.next();
//innerLoop++;
}
//Output Test
/*for(int i = 0; i < feedItems.size(); i++) {
Log.d("Title", feedItems.get(i).getTitle());
Log.d("Date", feedItems.get(i).getPubDate());
}*/
}
break;
case XmlPullParser.TEXT:
break;
case XmlPullParser.END_TAG:
break;
}
event = myParser.next();
}
parsingComplete = false;
}
catch (Exception e) {
e.printStackTrace();
}
}
public void fetchXML(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
URL url = new URL(address);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 );
conn.setConnectTimeout(15000 );
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();
xmlPullParserFactory = XmlPullParserFactory.newInstance();
XmlPullParser myparser = xmlPullParserFactory.newPullParser();
myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
myparser.setInput(stream, null);
parseXMLAndStoreIt(myparser);
stream.close();
}
catch (Exception e) {
}
}
});
thread.start();
}
}
You are calling fetchXML() from doInBackground, but fetchXML() starts a new thread and then immediately returns. Then doInBackground() immediately returns and onPostExecute() is called. However, at that point, the thread launched by fetchXML() has not had time to finish, so feedItems has not been properly set.
That's the wrong way to use an AsyncTask. Instead, you should do the fetching directly in the doInBackground() thread. Just rewrite fetchXML() to do the fetching itself, rather than launch a separate thread to do the fetching.

Asynctask unknown type execute

This is my first time with getting APIS to return the result JSON object. I think I have got the async task code right but I just don't know how to execute it. This is my class code.
For my layout all I have is one button with an onClick () method gg, a progress bar and one text view.
This is the async task:
public class MainActivity extends Activity
{
ProgressBar progressBar;
TextView responseView;
EditText emailText;
String URL;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
responseView = (TextView) findViewById(R.id.responseView);
emailText = (EditText) findViewById(R.id.emailText);
URL = "https://kgsearch.googleapis.com/v1/entities:search?query=taylor+swift&key=APIKEY&limit=1&indent=True";
}
public void gg(View v)
{
new RetrieveFeedTask.execute();
}
private class RetrieveFeedTask extends AsyncTask<Void, Void, String> {
private Exception exception;
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
responseView.setText("");
Toast.makeText(MainActivity.this, "pre execute", Toast.LENGTH_LONG).show();
}
protected String doInBackground(Void... urls) {
String email = emailText.getText().toString();
// Do some validation here
try {
URL url = new URL(URL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
return stringBuilder.toString();
}
finally{
urlConnection.disconnect();
}
}
catch(Exception e) {
Log.e("ERROR", e.getMessage(), e);
return null;
}
}
protected void onPostExecute(String response) {
if(response == null) {
response = "THERE WAS AN ERROR";
Toast.makeText(MainActivity.this, "post execute", Toast.LENGTH_LONG).show();
}
progressBar.setVisibility(View.GONE);
Log.i("INFO", response);
responseView.setText(response);
}
}
}
So in the public void gg(View v)
I call the .execute method but it gives me an error
Unknown type execute
Do I have to add some params to the execute method?
If so what?
Thanks.
Try
new RetrieveFeedTask().execute();

android update custom view in asynctask

Ok, I have a custom view which plays gifs from the internet. Therefor I need to add an url to my view to download the gif. But I can't seem to update my custom view inside my asynctask. I need to add an url string to my custom view gifView.setUrl(). It works in the onCreate Class but it gives me null in asynctask.
Oncreate class
GifView gifView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
id = extras.getInt("id");
String idStr = String.valueOf(id);
String extension = extras.getString("extension");
if(extension.equals(".gif")){
setContentView(R.layout.activity_post_gif);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
gifView = (GifView)findViewById(R.id.gifview);
titleStr = (TextView)findViewById(R.id.titleTXT);
postInfo = (TextView)findViewById(R.id.infoTXT);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
//the url
new getJsonInfoGif().execute("http://www.website.com/jsonApi");
}else{
Asynctask
public class getJsonInfoGif extends AsyncTask<String, Void, String>{
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("loading post...");
progressDialog.show();
}
#Override
protected String doInBackground(String... strings) {
return GET(strings[0]);
}
#Override
protected void onPostExecute(String res) {
try {
JSONObject jsonObject = new JSONObject("{'postinfo':[" + res + "]}");
JSONArray jsonArray = jsonObject.getJSONArray("postinfo");
JSONObject obj = jsonArray.getJSONObject(0);
//post title
titleStr.setText(obj.getString("name"));
//category and maker full name
//large image
JSONObject imgObj = obj.getJSONObject("thumbnails");
gifView.setUrl("http://www.website.com/my.gif");
} catch (JSONException e) {
e.printStackTrace();
}
if (progressDialog != null) {
progressDialog.dismiss();
}
}
}
GifView.java
public void setUrl(String urlStr){
this.urlStr = urlStr;
invalidate();
requestLayout();
}
public String getUrl(){
return this.urlStr;
}
public void init(final Context context)throws IOException{
setFocusable(true);
movie = null;
movieWidth = 0;
movieHeight = 0;
movieDuration = 0;
final Thread thread = new Thread(new Runnable() {
#Override
public void run(){
try{
Log.d("DEBUG", "URL" + urlStr);
URL url = new URL(urlStr);
try {
HttpURLConnection http = (HttpURLConnection) url.openConnection();
inputStream = http.getInputStream();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
movie = Movie.decodeStream(inputStream);
movieWidth = movie.width();
movieHeight = movie.height();
movieDuration = movie.duration();
((PostActivity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
invalidate();
requestLayout();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}catch (Exception e){
e.printStackTrace();
}
}
});
thread.start();
}
Here is the Log from the url, it gives me null if I add the url inside my asynctask in Activity.
11-07 14:41:58.821 5674-6076/svenmobile.tools.showcase D/DEBUGļ¹• URLnull
What I want to know is what the problem is and how to solve it if possible.
Thanks in advance, Sven
Maybe you called init() before setUrl().
You can pass it the url in the contructor, or public void init(final Context context, String urlStr)throws IOException{
I also suggest you to move all that network code to doInBackground

Progress Bar during the loading of a ListView

So, I want to display a spinning loading indicator while my ListView is being populated. I successfully have implemented the progress bar, BUT for some reason it disappears BEFORE all of the listings are displayed. What I want is the progressbar to be present during the TOTAL load time of the listings. Basically, what it seems like, each listing is being displayed one at a time, not all at once when they are all loaded.
What I'm doing is
1. Creating a new custom adapter class
2. Populating the ListView in an AsyncTask using this adapter class
3. Setting the ListView to this adapter
This works properly, the progress bar just disappears before all of the listings are displayed. Does anyone have any ideas?
Activity class:
public class MainActivity extends ActionBarActivity {
ArrayList<Location> arrayOfLocations;
LocationAdapter adapter;
// public static Bitmap bitmap;
Button refresh;
ProgressBar progress;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progress=(ProgressBar)findViewById(R.id.progressbar_loading);
// Construct the data source
arrayOfLocations = new ArrayList<Location>();
// Create the adapter to convert the array to views
adapter = new LocationAdapter(this, arrayOfLocations);
FillLocations myFill = new FillLocations();
myFill.execute();
refresh = (Button) findViewById(R.id.refresh);
refresh.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
finish();
startActivity(getIntent());
}
});
}
private class FillLocations extends AsyncTask<Integer, Void, String> {
String msg = "Done";
protected void onPreExecute() {
progress.setVisibility(View.VISIBLE);
}
// Decode image in background.
#Override
protected String doInBackground(Integer... params) {
String result = "";
InputStream isr = null;
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://afs.spotcontent.com/"); // YOUR
// PHP
// SCRIPT
// ADDRESS
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
isr = entity.getContent();
// resultView.setText("connected");
} catch (Exception e) {
Log.e("log_tag", "Error in http connection " + e.toString());
}
// convert response to string
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(isr, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
isr.close();
result = sb.toString();
} catch (Exception e) {
Log.e("log_tag", "Error converting result " + e.toString());
}
// parse json data
try {
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
final JSONObject json = jArray.getJSONObject(i);
try {
BitmapWorkerTask myTask = new BitmapWorkerTask(
json.getInt("ID"), json);
myTask.execute();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (Exception e) {
// TODO: handle exception
Log.e("log_tag", "Error Parsing Data " + e.toString());
}
return msg;
}
protected void onPostExecute(String msg) {
// Attach the adapter to a ListView
ListView listView = (ListView) findViewById(R.id.listView1);
// View header = (View) getLayoutInflater().inflate(
// R.layout.listview_header, null);
// listView.addHeaderView(header);
listView.setAdapter(adapter);
progress.setVisibility(View.GONE);
}
}
}
Adapter class:
public class LocationAdapter extends ArrayAdapter<Location> {
public LocationAdapter(Context context, ArrayList<Location> locations) {
super(context, R.layout.item_location, locations);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Location location = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_location, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
TextView tvDetails = (TextView) convertView.findViewById(R.id.tvDetails);
TextView tvDistance = (TextView) convertView.findViewById(R.id.tvDistance);
TextView tvHours = (TextView) convertView.findViewById(R.id.tvHours);
ImageView ivIcon = (ImageView) convertView.findViewById(R.id.imgIcon);
// Populate the data into the template view using the data object
tvName.setText(location.name);
tvDetails.setText(location.details);
tvDistance.setText(location.distance);
tvHours.setText(location.hours);
ivIcon.setImageBitmap(location.icon);
// Return the completed view to render on screen
return convertView;
}
}
The reason for that behavior is that you are starting multiple threads.
FillLocations preExecute --> SHOW ProgressBar
BitmapWorkerTask_1 --> new thread
BitmapWorkerTask_2 --> new thread
...
BitmapWorkerTask_N --> new thread
FillLocations postExecute --> HIDE ProgressBar
BitmapWorkerTask_K --> continue execution
BitmapWorkerTask_K+1 --> continue execution
etc.
If you want the list to be displayed until it's all loaded, Simply make BitmapWorker's processing synchronous. If you still want to display the list right away but keep the spinner until it's all finished, then keep a counter in your activity and increase it in preexecute and decrease it in postExecute of BitmapWorker via a setter. Once the counter hits 0, remove hide the progressBar.
In activity:
private int asynchCounter = 0;
private void updateCounter(int delta){
asynchCounter+=delta;
if(asynchCounter<=0){
progress.setVisibility(View.GONE);
}else{
progress.setVisibility(View.VISIBLE);
}
}
And instead of BitmapWorkerTask use
class CountedBitmapWorkerTask extends BitmapWorkerTask {
protected void onPreExecute() {
super.onPreExecute();
updateCounter(1);
}
protected void onPostExecute(String msg) {
super.onPostExecute();
updateCounter(-1);
}
}
I had this exact problem, to solve it I had to write AsyncTask complete listener. Which sends a notification to UI thread, that data was loaded and it has to change something, in this case hide the ProgressBar.
This is the basic example of how this should look like. I am not sure this will work for you after you copy it to your project, but complete listener is what you need, so after studying this case you should be able to find a solution.
AsyncTaskCompleteListener.java - listener interface.
public interface AsyncTaskCompleteListener {
public void onTaskComplete();
}
LoadDataTask.java
class LoadDataTask extends AsyncTask<Object, Object, Object> {
/* Your object types according to your task. */
private AsyncTaskCompleteListener callback; // Callback field
public LoadDataTask(AsyncTaskCompleteListener cb){
this.callback = cb;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Object doInBackground(String... urls) {
/* Your task here */
return result;
}
#Override
protected void onPostExecute(Object o) {
callback.onTaskComplete(); // Set the Callback
}
}
MainActivity.java
public class MainActivity implements AsyncTaskCompleteListener{
/* ...Other methods and fields... */
/* onTaskComplete method which fires after your data is loaded. */
#Override
public void onTaskComplete(){
// Hide ProgressBar
}
}
Self Plug: https://github.com/horvste/EasyWebPageDownloadForAndroid
This would separate the threading from the implementation and solve your problem. This is very similar to what Tony suggested except it's already implemented for you.
Github Readme:
Good for connecting to REST API's, HTML parsing, and many other uses. Using this library is meant to be easy:
Create a class which implements OnProgressUpdate
public class SampleClass implements OnProgressUpdate {
#Override
public void onUpdate(Integer percentProgress) {
}
#Override
public void onUpdateFailure() {
}
#Override
public void onSuccess(StringBuilder result) {
}
#Override
public void onFailure() {
}
}
}
Instantiate DownloadWebPage object
DownloadWebPage webPage = new DownloadWebPage(new SampleClass(), myUrl);
Call .downloadHtml() from the DownloadWebPage
webPage.downloadHtml();
Also if the asynchtask is updating properly and the amount of items is to large look here:
listing a listview is taking too much time and memory in android
Another option would be to only list a certain amount of items then have a next page button or gesture to deal with the ListView loading too slow.

Trouble upgrading my RSS feed reader app, from AsycTask to AsyncTaskLoader behavior

Hello I implemented a simple RSS Feed reader using an AsyncTask, and It works perfectly.
I am trying upgrade my little APP to work with an ASYNCTASKLOADER, to learn how to use Loaders.
Notice the two lines of code on the:
public void onCreate(Bundle savedInstanceState){
of the RSSMain class...
new getRSSFeeds().execute();
getLoaderManager().initLoader(0, null, callBacks1);
By un/commenting these two lines I decide which mode to try my app with.
When I attempt to read RSS Feeds with getLoaderManager, all I get is a blank Activity.
My code is attached. I must have some conceptual mistake on my code, since I am new to all these things. Does somebody now how to solve it?
Take into account I started programming for Android 3 weeks ago, and my code
may be far from perfect, so any comments towards improvement are welcome!
public class RSSMain extends ListActivity {
private ArrayList<rssentry> itemlist2 = null; //LIST OF ALL RSS FEEDS
private RSSListAdaptor2 rssadaptor2 = null; //A SINGLE RSS POST
private String sourceurl=null;
public final static String EXTRA_MESSAGE = "com.example.rssjosh.MESSAGE"; //DECLARE PAYLOAD MESSAGE FOR THE ACTIVITY-CALLING INTENT
private static final int LENGTH_SHORT = 0;
private static final int LENGTH_LONG = 1;
String toastxt="empty...";
Toast toast;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//LoaderManager lmanager = getLoaderManager().initLoader(0, null, new RSSLoaderCallback, getBaseContext());
//getLoaderManager().initLoader(0, savedInstanceState, new RSSLoader(null));
sourceurl="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
itemlist2 = new ArrayList<rssentry>();
getLoaderManager().initLoader(0, null, callBacks1); //CREATES AND INITS. LOADER (ASYNCTASKLOADER MODE)
//new getRSSFeeds().execute();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String s=null;
rssentry data = itemlist2.get(position); //GET THE RSSENTRY THAT WAS TOUCHED BY THE USER
//TEMPORARY TOAST TO CHECK CORRECT STRING FORMATION
//String toastxt="XD!";
//int duration = Toast.LENGTH_LONG; //toastxt=toastxt+data.title+"\n"+data.published+"\n"+data.link+"\n"+data.summary.substring(30,140)+"\n";
//FORM THE HTML TEXT TO BE SENT TO THE SIGLE-RSSFEED DISPLAY ACTIVITY
StringBuilder htmlString = new StringBuilder();
htmlString.append(data.title+"$");
htmlString.append("Published on: "+data.published+"$");
htmlString.append(data.summary+"$");
htmlString.append("URL: "+data.link+"$");
Intent intent = new Intent(this,Rssactivity.class);
//LOADS THE INTENT WITH THE <HTML> PAYLOAD
intent.putExtra(EXTRA_MESSAGE, htmlString.toString()); ///public final static String EXTRA_MESSAGE = "com.example.rssjosh.MESSAGE"; DECLARED ABOVE
startActivity(intent); //LAUNCHES INTENT
}
//SERVICE METHOD TO private String retrieveRSSFeed2(String urlToRssFeed)
// _URLstring -> INPUT_STREAM
private InputStream downloadUrl(String urlString) throws IOException {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// STARTS QUERYING THE STREAM
conn.connect();
InputStream stream = conn.getInputStream();
return stream;
}
//URL -> (INPUT_STREAM) -> List<rssentry> entries
//THIS VARIANT OF THE RETRIEVERSSFEED2 METHOD, RETURNS RESULT IN A STRING FORMAT (OPTIONAL METHOD)
private ArrayList<rssentry> retrieveRSSFeed2Str(String urlToRssFeed) throws XmlPullParserException, IOException
{
ArrayList<rssentry> itemlist = new ArrayList<rssentry>();
//INSTANTIATES A NEW PARSER "parsero", AND AN EMPTY RSSENTRY ARRAYLIST
InputStream stream = null;
//List<rssentry> entries = null; UPGRADED TO PUBLIC CLASS ATTRIBUTE
xmlparser parsero = new xmlparser();
//This Try does URL->Stream
try {
stream = downloadUrl(urlToRssFeed); //OBTAIN A CHARACTER STREAM FROM THE rssURL
itemlist = parsero.parse(stream); //PARSE STREAM AND STORE rssENTRIES IN THE "ENTRIES" ARRAYLIST <rssentry>
} finally {
if (stream != null) {
stream.close(); //CLOSE STREAM AFTER USING IT
}
}
return itemlist;
}
//GETS RSS FEED IN ASYNCHRONOUS MODE
class ATLgetfeeds extends AsyncTaskLoader <ArrayList<rssentry>>{
private ArrayList<rssentry> rsslist=null;
private ProgressDialog progress = null;
public ATLgetfeeds(Context context) {
super(context);
}
#Override
protected void onStartLoading() {
if (rsslist != null)
deliverResult(rsslist); // Use the cache
else
forceLoad();
}
#Override
public ArrayList<rssentry> loadInBackground() {
try {
itemlist2 = null; //<=THIS LIST IS TO BE LOADED WITH THE RSS URL BELOW
rsslist = retrieveRSSFeed2Str("http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest"); //SETS ITEMLIST2
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//LOADS DATA INTO RSSADAPTER (PARSER2)
rssadaptor2 = new RSSListAdaptor2(RSSMain.this, R.layout.rssitemview,rsslist);
return null;
}
#Override
public void deliverResult(ArrayList<rssentry> data) {
rsslist = data; // Caching
super.deliverResult(data);
}
#Override
protected void onReset() {
super.onReset();
// Stop the loader if it is currently running
onStopLoading();
rsslist = null;
}
#Override
public void onCanceled(ArrayList<rssentry> data) {
// Attempt to cancel the current async load
super.onCanceled(data);
rsslist = null;
}
protected void onPreExecute() {
progress = ProgressDialog.show( RSSMain.this, null, "RSSJosh Loading..."); //LOADING MESSAGE
// super.onPreExecute();
}
protected void onPostExecute(Void result) {
itemlist2=rsslist;
setListAdapter(rssadaptor2);
progress.dismiss(); //Dismisses loading progress dialog
//s super.onPostExecute(result);
}
}
//GETS RSS FEED IN ASYNCHRONOUS MODE
private class getRSSFeeds extends AsyncTask<Void, Void, Void>
{
private ProgressDialog progress = null;
ArrayList<rssentry> atlist = new ArrayList<rssentry>();
#Override
protected Void doInBackground(Void... params) {
try {
itemlist2 = null; //<=THIS LIST IS TO BE LOADED WITH THE RSS URL BELOW
atlist = retrieveRSSFeed2Str("http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest");
} catch (XmlPullParserException e) {
e.printStackTrace(); // TODO Auto-generated catch block
} catch (IOException e) {
e.printStackTrace(); // TODO Auto-generated catch block
}
//LOADS DATA INTO UI RSSADAPTER (PARSER2)
rssadaptor2 = new RSSListAdaptor2(RSSMain.this, R.layout.rssitemview,atlist);
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected void onPreExecute() {
progress = ProgressDialog.show( RSSMain.this, null, "RSSJosh Loading..."); //LOADING MESSAGE
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
setListAdapter(rssadaptor2);
itemlist2=atlist;
progress.dismiss(); //Dismisses loading progress dialog
super.onPostExecute(result);
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
//RSS ADAPTER (TYPE2) FOR STACK-OVERFLOW RSSFEEDS
private class RSSListAdaptor2 extends ArrayAdapter<rssentry>{
private List<rssentry> objects = null;
public RSSListAdaptor2(Context context, int textviewid, List<rssentry> objects) {
super(context, textviewid, objects);
this.objects = objects;
}
#Override
public int getCount() {
return ((null != objects) ? objects.size() : 0);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public rssentry getItem(int position) {
return ((null != objects) ? objects.get(position) : null);
}
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(null == view)
{
LayoutInflater vi = (LayoutInflater)RSSMain.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.rssitemview, null);
}
rssentry data = objects.get(position);
if(null != data)
{ //CREATE TEXTVIEW OBJECTS FORTITLE, DATE AND DESCRIPTION DATA
TextView title = (TextView)view.findViewById(R.id.txtTitle);
TextView date = (TextView)view.findViewById(R.id.txtDate);
TextView description = (TextView)view.findViewById(R.id.txtDescription);
//PUT TEXT ON TITLE AND DATE VIEWS
title.setText(data.title);
date.setText("Published on: " + data.published); //PREVIOUSLY date.setText("on " + data.date);
//PREPARE AND LOAD TEXT FOR THE SUMMARY VIEW
String txt=null;
//Clean and trim summary string before displaying
txt=data.summary.toString().substring(30,data.summary.toString().length());
if (txt.length()>=300)
txt=txt.substring(0,299)+"..."; ///DISPLAY A SUMMARY OF 300 CHARACTERS MAX, IN THE RSS HEADLINES
description.setText(txt); //PUT TEXT
}
return view;
}
}
LoaderManager.LoaderCallbacks<ArrayList<rssentry>> callBacks1 = new LoaderManager.LoaderCallbacks<ArrayList<rssentry>>() {
/* Implement the three callback methods here */
public android.content.Loader<ArrayList<rssentry>> onCreateLoader( //START LOADING
int arg0, Bundle arg1) {
// TODO Auto-generated method stub
android.content.Loader<ArrayList<rssentry>> rsslist=null;
//TEMPORARY TOAST TO DEBUG CORRECT STRING FORMATION
toastxt="Toastiee! Preparing for ATL Task";
toast = Toast.makeText(getBaseContext(), toastxt, LENGTH_SHORT);
toast.show();
ATLgetfeeds a= new ATLgetfeeds(getBaseContext());
//TEMPORARY TOAST TO DEBUG CORRECT STRING FORMATION
toastxt="Toastiee! ATL Task created";
toast = Toast.makeText(getBaseContext(), toastxt, LENGTH_SHORT);
toast.show();
return rsslist;
}
#Override
public void onLoadFinished( //START LOADING
android.content.Loader<ArrayList<rssentry>> arg0,
ArrayList<rssentry> arg1) {
// TODO Auto-generated method stub
}
#Override
public void onLoaderReset(android.content.Loader<ArrayList<rssentry>> arg0) {
// TODO Auto-generated method stub
}
};
}

Categories