Welcome to part 8 of my Android development tutorial. Today I’m going to show you how to make an android xml parser using the DOM. I’ll cover XmlPullParser next time.
I also cover numerous other topics including : How to use AsyncTask to execute threads in the background : How to write to the GUI from a thread : How to use Log.d : How to connect to a web service : Much more…
The code & video below will help you learn this stuff completely.
If you like videos like this, it helps to tell Google+ with a click here [googleplusone]
Code From the Video
Here is all of the code in one package Android Stock Quote App.
activity_stock_info.xml
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TableRow android:id="@+id/tableRow1" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/companyNameTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/activity_horizontal_margin" android:text="Medium Text" android:textAppearance="?android:attr/textAppearanceMedium" /> </TableRow> <TableRow android:id="@+id/tableRow2" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/yearLowTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/activity_horizontal_margin" android:text="@string/stock_year_low" android:layout_weight="1" /> <TextView android:id="@+id/yearHighTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stock_year_high" android:layout_weight="1" /> </TableRow> <TableRow android:id="@+id/tableRow3" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/activity_horizontal_margin" > <TextView android:id="@+id/daysLowTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stock_days_low" android:layout_weight="1" /> <TextView android:id="@+id/daysHighTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stock_days_high" android:layout_weight="1" /> </TableRow> <TableRow android:id="@+id/tableRow4" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/activity_horizontal_margin" > <TextView android:id="@+id/lastTradePriceOnlyTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/last_trade_price_only" android:layout_weight="1" /> <TextView android:id="@+id/changeTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/change" android:layout_weight="1" /> </TableRow> <TableRow android:id="@+id/tableRow5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/activity_horizontal_margin" > <TextView android:id="@+id/daysRangeTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/days_range" /> </TableRow> </TableLayout>
StockInfoActivity.java
package com.newthinktank.stockquotes; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.util.Log; import android.view.Menu; import android.widget.TextView; public class StockInfoActivity extends Activity { // Used to identify the app in the LogCat, so I // can output messages and debug the program private static final String TAG = "STOCKQUOTE"; // Define the TextViews I use in activity_stock_info.xml TextView companyNameTextView; TextView yearLowTextView; TextView yearHighTextView; TextView daysLowTextView; TextView daysHighTextView; TextView lastTradePriceOnlyTextView; TextView changeTextView; TextView daysRangeTextView; // XML node keys static final String KEY_ITEM = "quote"; // parent node static final String KEY_NAME = "Name"; static final String KEY_YEAR_LOW = "YearLow"; static final String KEY_YEAR_HIGH = "YearHigh"; static final String KEY_DAYS_LOW = "DaysLow"; static final String KEY_DAYS_HIGH = "DaysHigh"; static final String KEY_LAST_TRADE_PRICE = "LastTradePriceOnly"; static final String KEY_CHANGE = "Change"; static final String KEY_DAYS_RANGE = "DaysRange"; // XML Data to Retrieve String name = ""; String yearLow = ""; String yearHigh = ""; String daysLow = ""; String daysHigh = ""; String lastTradePriceOnly = ""; String change = ""; String daysRange = ""; // Used to make the URL to call for XML data String yahooURLFirst = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quote%20where%20symbol%20in%20(%22"; String yahooURLSecond = "%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"; // NEW STUFF // Holds values pulled from the XML document using XmlPullParser String[][] xmlPullParserArray = {{"AverageDailyVolume", "0"}, {"Change", "0"}, {"DaysLow", "0"}, {"DaysHigh", "0"}, {"YearLow", "0"}, {"YearHigh", "0"}, {"MarketCapitalization", "0"}, {"LastTradePriceOnly", "0"}, {"DaysRange", "0"}, {"Name", "0"}, {"Symbol", "0"}, {"Volume", "0"}, {"StockExchange", "0"}}; int parserArrayIncrement = 0; // END OF NEW STUFF @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Creates the window used for the UI setContentView(R.layout.activity_stock_info); // Get the message from the intent that has the stock symbol Intent intent = getIntent(); String stockSymbol = intent.getStringExtra(MainActivity.STOCK_SYMBOL); // Initialize TextViews companyNameTextView = (TextView) findViewById(R.id.companyNameTextView); yearLowTextView = (TextView) findViewById(R.id.yearLowTextView); yearHighTextView = (TextView) findViewById(R.id.yearHighTextView); daysLowTextView = (TextView) findViewById(R.id.daysLowTextView); daysHighTextView = (TextView) findViewById(R.id.daysHighTextView); lastTradePriceOnlyTextView = (TextView) findViewById(R.id.lastTradePriceOnlyTextView); changeTextView = (TextView) findViewById(R.id.changeTextView); daysRangeTextView = (TextView) findViewById(R.id.daysRangeTextView); // Sends a message to the LogCat Log.d(TAG, "Before URL Creation " + stockSymbol); // Create the YQL query final String yqlURL = yahooURLFirst + stockSymbol + yahooURLSecond; // The Android UI toolkit is not thread safe and must always be // manipulated on the UI thread. This means if I want to perform // any network operations like grabbing xml data, I have to do it // in its own thread. The problem is that you can't write to the // GUI from outside the main activity. AsyncTask solves those problems new MyAsyncTask().execute(yqlURL); } // Use AsyncTask if you need to perform background tasks, but also need // to change components on the GUI. Put the background operations in // doInBackground. Put the GUI manipulation code in onPostExecute private class MyAsyncTask extends AsyncTask<String, String, String>{ // String... arg0 is the same as String[] args protected String doInBackground(String... args) { try { // Get the XML URL that was passed in URL url = new URL(args[0]); // connection is the communications link between the // application and a URL that we will read from. URLConnection connection; connection = url.openConnection(); // Used to take advantage of HTTP specific features. // Provides tools that tell us if a connection was // made, lost and other HTTP Status Codes HttpURLConnection httpConnection = (HttpURLConnection)connection; // Did we connect properly the the URL? int responseCode = httpConnection.getResponseCode(); // Tests if responseCode == 200 Good Connection if (responseCode == HttpURLConnection.HTTP_OK) { // Reads data from the connection InputStream in = httpConnection.getInputStream(); // Provides a way to parse DOM object trees from XML documents DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // Provides a DOM Document from an xml page DocumentBuilder db = dbf.newDocumentBuilder(); // Parse the Yahoo Financial YQL Stock XML File Document dom = db.parse(in); // The root element is query Element docEle = dom.getDocumentElement(); // Get a list of quote nodes NodeList nl = docEle.getElementsByTagName("quote"); // Checks to make sure we found a quote tag if (nl != null && nl.getLength() > 0) { // Cycles through if we find multiple quote tags // Mainly used for demonstration purposes for (int i = 0 ; i < nl.getLength(); i++) { // Passes the root element of the XML page, so // that the function below can search for the // information needed StockInfo theStock = getStockInformation(docEle); // Gets the values stored in the StockInfo object daysLow = theStock.getDaysLow(); daysHigh = theStock.getDaysHigh(); yearLow = theStock.getYearLow(); yearHigh = theStock.getYearHigh(); name = theStock.getName(); lastTradePriceOnly = theStock.getLastTradePriceOnly(); change = theStock.getChange(); daysRange = theStock.getDaysRange(); // Outputs information for tracking reasons only // Log.d(TAG, "Stock Name " + name); // Log.d(TAG, "Stock Year High " + yearHigh); // Log.d(TAG, "Stock Year Low " + yearLow); // Log.d(TAG, "Stock Days High " + daysHigh); // Log.d(TAG, "Stock Days Low " + daysLow); } } } } catch (MalformedURLException e) { Log.d(TAG, "MalformedURLException", e); } catch (IOException e) { Log.d(TAG, "IOException", e); } catch (ParserConfigurationException e) { Log.d(TAG, "Parser Configuration Exception", e); } catch (SAXException e) { Log.d(TAG, "SAX Exception", e); } finally { } // NEW STUFF try{ Log.d("test","In XmlPullParser"); // It is recommended to use the XmlPullParser because // it is faster and requires less memory then the DOM API // XmlPullParserFactory provides you with the ability to // create pull parsers that parse XML documents XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); // Parser supports XML namespaces factory.setNamespaceAware(true); // Provides the methods needed to parse XML documents XmlPullParser parser = factory.newPullParser(); // InputStreamReader converts bytes of data into a stream // of characters parser.setInput(new InputStreamReader(getUrlData(args[0]))); // Passes the parser and the first tag in the XML document // for processing beginDocument(parser,"query"); // Get the currently targeted event type, which starts // as START_DOCUMENT int eventType = parser.getEventType(); do{ // Cycles through elements in the XML document while // neither a start or end tag are found nextElement(parser); // Switch to the next element parser.next(); // Get the current event type eventType = parser.getEventType(); // Check if a value was found between 2 tags if(eventType == XmlPullParser.TEXT){ // Get the text from between the tags String valueFromXML = parser.getText(); // Store it in an array with the corresponding tag // value xmlPullParserArray[parserArrayIncrement][1] = valueFromXML; Log.d("test", "Values: " + xmlPullParserArray[parserArrayIncrement++][1]); } } while (eventType != XmlPullParser.END_DOCUMENT) ; } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { } // Print out the tags and associated values that // were found for(int i = 0; i < xmlPullParserArray.length; i++){ Log.d("test", xmlPullParserArray[i][0] + ":" + xmlPullParserArray[i][1]); } // END OF NEW STUFF return null; } // NEW STUFF public InputStream getUrlData(String url) throws URISyntaxException, ClientProtocolException, IOException { // Used to get access to HTTP resources DefaultHttpClient client = new DefaultHttpClient(); // Retrieves information from the URL HttpGet method = new HttpGet(new URI(url)); // Gets a response from the client on whether the // connection is stable HttpResponse res = client.execute(method); // An HTTPEntity may be returned using getEntity() which tells // the system where the content is coming from return res.getEntity().getContent(); } public final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException { int type; // next() advances to the next element in the XML // document being a starting or ending tag, or a value // or the END_DOCUMENT while ((type=parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) { ; } // Throw an error if a start tag isn't found if (type != parser.START_TAG) { throw new XmlPullParserException("No start tag found"); } // Verify that the tag passed in is the first tag in the XML // document if (!parser.getName().equals(firstElementName)) { throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + ", expected " + firstElementName); } } public final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException { int type; // Cycles through elements in the XML document while // neither a start or end tag are found while ((type=parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) { ; } } // END OF NEW STUFF // Changes the values for a bunch of TextViews on the GUI protected void onPostExecute(String result){ companyNameTextView.setText(name); yearLowTextView.setText("Year Low: " + yearLow); yearHighTextView.setText("Year High: " + yearHigh); daysLowTextView.setText("Days Low: " + daysLow); daysHighTextView.setText("Days High: " + daysHigh); lastTradePriceOnlyTextView.setText("Last Price: " + lastTradePriceOnly); changeTextView.setText("Change: " + change); daysRangeTextView.setText("Daily Price Range: " + daysRange); } } // Sends the root xml tag and the tag name we are searching for to // getTextValue for processing. Then uses that information to create // a new StockInfo object private StockInfo getStockInformation(Element entry){ String stockName = getTextValue(entry, "Name"); String stockYearLow = getTextValue(entry, "YearLow"); String stockYearHigh = getTextValue(entry, "YearHigh"); String stockDaysLow = getTextValue(entry, "DaysLow"); String stockDaysHigh = getTextValue(entry, "DaysHigh"); String stocklastTradePriceOnlyTextView = getTextValue(entry, "LastTradePriceOnly"); String stockChange = getTextValue(entry, "Change"); String stockDaysRange = getTextValue(entry, "DaysRange"); StockInfo theStock = new StockInfo(stockDaysLow, stockDaysHigh, stockYearLow, stockYearHigh, stockName, stocklastTradePriceOnlyTextView, stockChange, stockDaysRange); return theStock; } // Searches through the XML document for a tag that matches // the tagName passed in. Then it gets the value from that // tag and returns it private String getTextValue(Element entry, String tagName){ String tagValueToReturn = null; NodeList nl = entry.getElementsByTagName(tagName); if(nl != null && nl.getLength() > 0){ Element element = (Element) nl.item(0); tagValueToReturn = element.getFirstChild().getNodeValue(); } return tagValueToReturn; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.stock_info, menu); return true; } }
Hello Derek, I want to thank you for your awesome content and support.
Im new to this all and want to create a 2d game like jetpack joyride. How long will this take if I spend 6 hours a day learning and trying?
thanks.
You are very welcome 🙂 Eventually I’ll start making games. Actually it is going to start very soon. If you understand the following parts of my Java video tutorial : 1 -7, 9, 11 – 18 and go through the Android tutorial you’ll be ready to go when I start making games. Have fun
Hey Derek,
Thanks for all the great tutorials.
I just completed Tut #8. Am getting a Source Not Found error for ActivityThread.performLaunchActivity
ideas??
I provide all of the code on my site. If you can give me all the errors that pertain to your classes and the lines the errors are on I may be able to help
Excellent Video, pretty easy to understand
Thank you very much 🙂 Always feel free to ask questions
Hi Raj,
I have been following your tutorials and I must tell you that this is one of the best Android tutorials that I have ever seen. I have learned a lot by listening your tutorials and following the same to create applications. FYI, I have not only bookmarked your site and have also forwarded your links to my friends. Are you are planning to incorporate tutorials based on Sherlock Themes and GUI design? Though, I am a beginner to Android, I am a Sr.Application Developer working on Java and othe technologies for the last 13 years. Your style of intstructions and tutoring has actually taught me to enhance my skills in Android within a shorter time frame. Looking forward to see more advanced tutorials on Android. Once again, thanks for sharing the knowledge with others who are eager to learn. Wishing you the best Derek.
Cheers!
Raj
Hi Raj,
Thank you for the kind message 🙂 I’m very happy that you are enjoying the Android tutorials. I’m really working to make them as good as possible. Sorry they aren’t coming out faster, but my real world job has been taking all my time. ( This is just a hobby for me )
Yes I will cover themes and will show how to make much better looking apps in the future. As you can tell, I’m trying to cover as many topics as possible in each tutorial, while trying to avoid getting boring.
Thanks again
Derek
Thanks Derek!
I really appreciate your videos. I really have nothing specific to ask, but I know how much effort goes into these and I wanted you to know that you’re being viewed and thanked.
Keep up!
OG
You’re very welcome 🙂 Thank you for visiting my little site and taking the time to send a nice message. I appreciate it!
I have been trying to modify the code from the tutorial to read attributes from XML elements. Like this:
I cant seem to get it to work, no matter what my methods always return null. Any suggestions on how to implement this?
I’m sorry, but the xml didn’t transfer over in the comment you left. Try putting it between code tags
Like that.
Okay, that didn’t work. Imagine there’s a “” at the end.
time from=”2013-05-26″ to=”2013-05-29″ type=”flood”
I’ll just provide the link:
http://www.yr.no/place/Norway/Telemark/Sauherad/Gvarv/forecast_hour_by_hour.xml
As you see the data we want is inside the attributes of the tags.
Check out part 9 of my Android Development Tutorial. It may be easier to use XmlPullParser.
Derek,
Thanks for your tutorials. I have been following them recently.
I have a question for you for this tutorial. The app failed to load because of the following message:
android.widget.ScrollView cannot be cast to android.widget.TableLayout.
Do you know what might be the cause of this problem?
Thanks!
OK. I figured out the problem.
In your MainActivity.java,
you have:
stockTableScrollView = (TableLayout) findViewById(R.id.stockTableScrollView);
where the type of stockTableScrollView is TableLayout, but in your activity_main.xml
stockTableScrollView is the id of a scrollView.
Thanks again for your tutorials. Keep going!
Thank you for taking the time to post your solution. That is much appreciated 🙂
I’m having this problem to, but I don’t know how to fix it. Maybe the answer is staring me in the face but I’ve been changing values and nothing seems to be working. What am I missing?
What errors are you getting in your LogCat panel? Are you using my code?
I’ve managed to fix it, using your code and a code compare tool I found online, I tracked it down to having an extra letter on one line of my XML code that was doing me over. It all works now.
I’m glad you fixed it 🙂
So how did you solve this?
Change the name of the Table Layout under the Scroll View of activity_main.xml, as stockTableScrollView. And give the scroll view some other ID.
Hope Derek I am correct.
Thank you, I was also having the same issue
Comment
Thanks for the excellent tutorials.
I believe your app runs well. But there are several bugs in the source code on the web pages. I suggest you put the whole project file on the web.
1. need to set TableLayout’s id in activity_main.xml
2. Sometimes the quote does not contain DaysLow/High. Need to handle it in getTextValue, otherwise the app crashes.
private String getTextValue(Element entry, String tagName) {
String tagValueToReturn = "";
NodeList nl = entry.getElementsByTagName(tagName);
if (nl != null && nl.getLength() > 0) {
Element element = (Element) nl.item(0);
if (element.getChildNodes().getLength() > 0)
tagValueToReturn = element.getFirstChild().getNodeValue();
}
return tagValueToReturn;
}
You’re very welcome :)Yes I didn’t go through how to catch all the errors. Sorry I made a judgement call to cover as much as possible, but not to necessarily go through extensive debugging. Here is a link to the whole package http://www.newthinktank.com/wordpress/StockQuotes.zip
I also made some changes in part 9 of the tutorial and provide that package here as well http://www.newthinktank.com/wordpress/StockQuotes2.zip
I’m sorry you had to repost a bunch of times. I get attacked hundreds of times a day and so I don’t let comments go up without approval.
I hope all that makes sense? Thank you for the input and code fixes 🙂
Derek
Do you have any idea why mine is breaking on
int responseCode = httpConnection.getResponseCode() ?
I don’t know much about log cat put from Log.d print outs I have figured out that that is the line where it breaks. If you want more info from logcat, could you tell me how to find it?
You can find the LogCat here Window – Show View – Other… – Android – LogCat
I understand how to open up logcat, but I don’t know how to find the pertinent info. All I can tell is that it says the error is at doInBackground.
You need to look for your specific class files in the LogCat. Some times you have to run the program more then once to get the LogCat to work right
Actually, it says “missing internet permission.” As far as I can tell I’ve done exactly what you said to do though. Did you set an internet permission somewhere?
Sorry about that. You need
in the manifest file. I have it set up properly in the package. I should have put more emphasis on that in the video
I’ve actually now got it all figured out.
Sorry I couldn’t get to you quicker 🙁
Hello Derek and thanks for the videos.
One question that has been confusing me. The overall package name is “com.newthinktank.stockqutoes”, but then there’s a line in MainActivity that says “public final static String STOCK_SYMBOL = “com.example.myfirstapp.STOCK”. Why are the package names different here? It’s probably something obvious but I’d appreciate if you could tell me!
Thanks
This is just a common practice in Android that is used often. You don’t have to define everything as Strings though. As the tutorial continues you’ll notice that I start passing other data types between activities. Sorry about not explaining that better
Hi, I’m trying to add a button to delete individual stock entries. I’ve added a button but I can’t get it delete the correct view and remove the right saved preferences…
I have this code… it always deletes the top one, and never deletes stuff from savedpreferences… any ideas?
public OnClickListener deleteStockListener = new OnClickListener(){
public void onClick(View v) {
String[] stocks = stockSymbolsEntered.getAll().keySet().toArray(new String[0]);
int id = 0;
for (int i = 0; i < stocks.length; i++){
if(stockSymbolEditText.getText().toString().equals(stocks[i])){
id = i;
break;
}
}
stockTableScrollView.removeViewAt(id);
SharedPreferences.Editor preferencesEditor = stockSymbolsEntered.edit();
preferencesEditor.remove(stockSymbolEditText.getText().toString());
preferencesEditor.apply();
}
};
Hi Derek, I know it’s not exactly part of the tutorial but do you have any ideas on how to solve this problem?
First, fantastic tutorials, I really appreciate you putting forth the effort to make sure a great contribution.
I’ve had pretty good success getting thing to work, but got an exception that my StockInfoActivity is not in the manifest. Is that required? Or is there another way to register the activity.
Thanks again…
Thank you very much 🙂 The Activities should automatically be placed in the manifest as you create them. If they aren’t you should try updating the Android plugin. (Help -> Check For Updates…)
Hey Derek,
Thank you very much for these tutorials…
Your work is being extremely helpful to me.
I am following these tutorials and I have watched 8 of them, understood everything very properly.
But in the 8th one, my LogCat says “missing INTERNET permission?” and there are 24 different errors, I have done everything as you have explained, so please help me with this.
Again Thank you very much man, you are AWESOME… 🙂
Hey,
Thank you very much for the nice compliments. You need to put the following line in your manifest file right after you define the version of android you are using.
I hope that helps
Derek
Hey Derek,
Thanks for the great tutorials. While following #8, I am having an exception as below.
java.io.EOFException
at libcore.io.Streams.readAsciiLine(Streams.java:203)
at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573)
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283)
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:495)
at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)
Am I missing something here? The exception is at the time of reading the response code.
Earlier I got the missing permission issue wrt Internet which I resolved by adding
Needless to say, your tutorials are simply awesome.
Hey Paresh,
Thank you 🙂 I’m glad you are enjoying them.
There was a bug in Android that was caused when url connections were recycled. Try updating your in Eclipse.
Also, try downloading the completed package I provide to make sure there isn’t a typo some place. Since there was no errors in your specific class files in the src folder though, but instead in the SDK I’m guessing the bug I mentioned above is causing the problem.
I hope that helps.
awesome video thanks a lot learnt quiete a few thing
Thank you 🙂
Hi,
I have followed your tutorials and I am getting quite a few RunTime errors. First 1 being: “FATAL EXCEPTION: AsyncTask #3”
I have looked through multiple forums and tried various solutions, none of which have worked.
Any suggestions will be appreciated.
LogCat:
10-14 09:57:47.020: E/AndroidRuntime(861): at android.os.AsyncTask$3.done(AsyncTask.java:299)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
10-14 09:57:47.020: E/AndroidRuntime(861): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.lang.Thread.run(Thread.java:841)
10-14 09:57:47.020: E/AndroidRuntime(861): Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.net.InetAddress.getAllByName(InetAddress.java:214)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpConnection.(HttpConnection.java:70)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpConnection.(HttpConnection.java:50)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
10-14 09:57:47.020: E/AndroidRuntime(861): at com.kings.stockquote.StockInfoActivity$MyAsyncTask.doInBackground(StockInfoActivity.java:96)
10-14 09:57:47.020: E/AndroidRuntime(861): at com.kings.stockquote.StockInfoActivity$MyAsyncTask.doInBackground(StockInfoActivity.java:1)
10-14 09:57:47.020: E/AndroidRuntime(861): at android.os.AsyncTask$2.call(AsyncTask.java:287)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
10-14 09:57:47.020: E/AndroidRuntime(861): … 4 more
10-14 09:57:47.020: E/AndroidRuntime(861): Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.io.Posix.getaddrinfo(Native Method)
10-14 09:57:47.020: E/AndroidRuntime(861): at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:61)
10-14 09:57:47.020: E/AndroidRuntime(861): at java.net.InetAddress.lookupHostByName(InetAddress.java:405)
10-14 09:57:47.020: E/AndroidRuntime(861): … 21 more
10-14 09:57:47.020: E/AndroidRuntime(861): Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied)
10-14 09:57:47.020: E/AndroidRuntime(861): … 24 more
10-14 09:57:48.380: I/Choreographer(861): Skipped 42 frames! The application may be doing too much work on its main thread.
10-14 09:57:49.112: W/EGL_emulation(861): eglSurfaceAttrib not implemented
10-14 09:57:49.151: I/Choreographer(861): Skipped 46 frames! The application may be doing too much work on its main thread.
Try running the complete package for my Android Stock Picking App. That will solve the error issue
I found the error in my manifest file and it worked the first time I ran it but now I am getting the exact same error… I even created a new workspace with your package and still the same.
Please help.
I’m sorry what is the error?
Hello Derek,
thanks a lot for the your videos so far, giving us the chance to learn Android development!
By the way I also struggled with the line
int responseCode = httpConnection.getResponseCode()
having had an IOException. I then added the line
to my manifest and it still fails executing the myTask.doInBackground thing..
Trying to debug I always receive the message No source code available. I am sure it somehow needs to be mapped, if so: Which code exactly and how?
Most I wonder that the logCat window does not come up with the messages which are written in the catch blocks. The one and only message which I receive is the “Before URL Creation ” in onCreate.
Do you have an idea about how to figure out what is going on here?
You’re very welcome 🙂 The easiest way to find bugs is to download the complete package for the Android Stock Quote App.
Then compare the files in my src directory to yours using a tool like DiffNow. The only other files you may need to look at are the Manifest and the layout files.
I hope that helps
Derek, I’ve downloaded and ran the completed Stock Quote app from your website, but I still get the “FATAL EXCEPTION” error described above.
Does anyone see the same problem?
Thank you.
Actually, here’s some additional info about the problem above. When I open your app in Eclipse StockInfoActivity.java shows a lot of errors.
For example the error for line 1 is:
“Multiple markers at this line
– The type java.lang.Object cannot be resolved. It is indirectly referenced from
required .class files
– The type java.lang.String cannot be resolved. It is indirectly referenced from
required .class files”
I ‘solved’ this problem by changing project.properties file from ‘target=android-17’ to ‘target=android-19’. This enabled me to run the app in the emulator, but it crashes with the ‘FATAL ERROR’ above.
Thanks for helping others that may have that problem 🙂
So I’m using Android Studio to do these tutorials, and trying to set up rows in the xml design tab seems pretty finicky. It usually defaults to assigning a textview with an android:layout_column. In your tutorial, you don’t use layout_column, but instead use layout_weight. It seems like layout_weight causes a lot less formatting headaches, but is layout_column supposed to be a better formatting option in TableLayouts?
Thanks!
I don’t think so. layout_weight is all about the total space available. So if you 1 for one component and 3 for the other they divide the total space 4 so that the second component gets 3/4ths of the space and the other gets 1/4th.
layout_column is a sort of measurement that I don’t care for because it seems to be hard to control.
great tutorial. Sir, please also cover the wifi direct topics in simple and detailed manner.
thanks……..
Thank you 🙂 I definitely will do that
This tutorial is amazing!
I have lots of Java experience, and with this tutorial I not only learn you to develop Android apps, but I UNDERSTAND what I am doing and why.
The example used to teach is adding an incredible value since it allow to understand each code written linking it to a “meaningful” result.
One question: The app works great on my Galaxy Note when holding it vertically, but when I put it horizontally, the row height is much too high. Any idea on how to fix this?
Thanks a lot for this incredible tutorials.
Cedric.
P.S.: I use Android Studio to develop.
Thank you Cedric, I’m happy that you are finding it useful. The reason why you are having the problem when you rotate is because I didn’t create a horizontal layout for the app. I get to how you can do that later in the tutorial. In part 19 of this series I cover it.
Hi, i am getting this error message:
11-14 14:57:05.417: D/AndroidRuntime(2183): Shutting down VM
11-14 14:57:05.417: W/dalvikvm(2183): threadid=1: thread exiting with uncaught exception (group=0xb0f6e648)
11-14 14:57:05.417: E/AndroidRuntime(2183): FATAL EXCEPTION: main
11-14 14:57:05.417: E/AndroidRuntime(2183): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ikresoft.stockquote/com.ikresoft.stockquote.MainActivity}: java.lang.ClassCastException: android.widget.ScrollView cannot be cast to android.widget.TableLayout
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.ActivityThread.access$600(ActivityThread.java:141)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.os.Handler.dispatchMessage(Handler.java:99)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.os.Looper.loop(Looper.java:137)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.ActivityThread.main(ActivityThread.java:5103)
11-14 14:57:05.417: E/AndroidRuntime(2183): at java.lang.reflect.Method.invokeNative(Native Method)
11-14 14:57:05.417: E/AndroidRuntime(2183): at java.lang.reflect.Method.invoke(Method.java:525)
11-14 14:57:05.417: E/AndroidRuntime(2183): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
11-14 14:57:05.417: E/AndroidRuntime(2183): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-14 14:57:05.417: E/AndroidRuntime(2183): at dalvik.system.NativeStart.main(Native Method)
11-14 14:57:05.417: E/AndroidRuntime(2183): Caused by: java.lang.ClassCastException: android.widget.ScrollView cannot be cast to android.widget.TableLayout
11-14 14:57:05.417: E/AndroidRuntime(2183): at com.ikresoft.stockquote.MainActivity.onCreate(MainActivity.java:40)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.Activity.performCreate(Activity.java:5133)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
11-14 14:57:05.417: E/AndroidRuntime(2183): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
11-14 14:57:05.417: E/AndroidRuntime(2183): ... 11 more
How can i solve this?
Thanks.
After the video there is a link named Android Stock Quote App
Click it and download the whole complete package and try running it. That will clear up any typos. Then you can compare my class files, layout files and the manifest to yours with something like diffnow.com
I finally finish this tutorial 8!!, First, I want to thank you for sharing some of your experience and knowledge with us. I have a few months trying to learn this and I have found your videos not only really informative but pedagogically sound to understand the concepts. It helps a lot your method of explaining what it does and why , while you are typing the code.
I finish this tutorial and I don’t find any red flag on my code however my emulator won’t lunch. I also copy the whole package and try to run it and I got the same response. Should I move on to tutorial 9 or focus on debugging it first?
the message I am getting is
….emulator fail to lunch.. I tried 3 different emulators.
May be my pc is the problem. Is there any labtop minimum requirements that you recommend for developing in eclipse?
Once againg thanks
VictoR
Hi Victor, I’m very happy that you are enjoying the tutorials. It sounds like you have an installation issue. I cover how to install all of the new Android development tools here. Tell me if you need any more help 🙂
Hey Derek, just wanted to ask you a question.
Do you recommend learning all the commands like DocumentBuilder, Element etc in the MyAsyncTask?
No there is no need to memorize. In the beginning you’ll do a lot of copying and pasting from previous code. After a while you’ll remember things naturally. Comment your code very well to help.
Hello Derek,
Great work! Thank you!
There seems to be an issue with the Yahoo page.
While the initial page (https://developer.yahoo.com/yql/console/?q=show%20tables&env=store://datatables.org/alltableswithkeys#h=select+*+from+yahoo.finance.quote+where+symbol+in+%28%22MSFT%22%29) is reachable from my computer, “THE REST QUERY” page (https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quote%20where%20symbol%20in%20(%22MSFT%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys) is not. The same situation with my phone.
After some investigation (it’s amazing how many people have this problem), I understood that there could be a problem with my home internet provider filtering somehow the “query.yahooapis.com” domain.
Switching my phone connection from home-wireless network to “mobile data”, I was able to reach “THE REST QUERY” page.
Thank you again for your great work.
Best regards,
B
Thank you very much for pointing that out for anyone else that may have that problem 🙂
Hi Derek,
I have just finished going through all the tutorials for this project and it appeared that everything was in order. However, when I went to run the app in an emulator the app started and then instantly closed. I have tried two different emulators and the same thing happened.
I then downloaded the complete package from this webpage and set it up in Eclipse and attempted to run it. Exactly the same thing happened as before.
Is there anything I can do about this?
Hi Oliver,
Sorry about the problems. I’m guessing that Yahoo changed their tags and that is the issue. Just in the past few weeks I have been getting complaints. I’ll be doing a new Android tutorials starting this month. This time I’ll try not to use anything that could possibly break.
Superb fantastic series Derek.
App runs perfectly well, made some mistakes, but as you suggested above to use DiffNow tool was able to grab it.
Thanks…. Learning is Fun
Great! I’m happy that you got everything running 🙂
Hi Derek,
When I press print, it prints the whole website out. Is there a way to only print the code?
Hi Jeff, Put your mouse over the top right edge of the code and then either click the View Source or print icons that show.
Hi Derek,
Nice video tutorial. I had learn a lot from videos till now. Will complete the whole tutorial soon. I test the app in your tutorial on my Nexus 7 and not on the emulator as it’s very slow.
I got two errors while testing the app.
I) Once you populate the app with stocks and then you tilt the tablet(change orientation to horizontal from vertical), all list is gone and replaced by a single stock which is the last stock which you have entered(say YHOO)
II) You cannot enter a wrong symbol as it gives error after pressing the Quote button that this app have been stopped.
Can you please fix them. In the first error can you also tell how to fix the app to run only on vertical mode.
Sorry about the errors. I should have stated that the apps weren’t optimized, but instead were structured more to cover as much as possible.
I’m making a new Android tutorial that will fix those issues in the next few weeks.
Hey Derek,
I just finished with this tutorial. I ran the program, and while it’s not catching any errors, all of the stock information returns empty when I hit the quote button. Everything else seems to be working fine, including the web button.
I’ve been going my code and comparing it to yours, but I can’t seem to find what’s wrong. Do you have any ideas as to what’s causing this?
I think the feed at Yahoo has changed. To make it work you’ll just need to update to the new tags on Yahoo. Sorry about that. Next time I’ll use my own web service.
Yeah, I just worked it out and they did change it.
Thanks for the help, and keep up the good work!
Hey
can you tell me what did you do because I’m also facing the same problem
Hi Derek,
I’ve done all the things as you have shown in this tutorial and previous but the app didn’t work. I executed the program into my android device, the app started but when i enetred the symbol of a company i.e msft and aapl and hit enter nothing happened. Plz help me solve this problem.
Try downloading the package I provide and tell me if that doesn’t work. Yahoo may have changed their tags.
Hi Derek,
First of all thank u again for a wonderful tutorial!
I have a problem, after I press the ‘Quote’ button the app crashes.
Because I wrote the code manually, I compared my code with the one u provided,
and changed the ‘src’ folder and all its content to be same as your code, as well as the ‘AndroidManifest.xml’, but it still crashes!
can u please help me solve the problem?
Btw the ‘Web’ button works perfectly.
Sorry about that. I think Yahoo randomly changes their feed. You can fix it by going in and changing based on their new feed. I’ll eliminate this issue by showing how to build your own web services very soon.
Derek, thanks so much for these awesome tutorials !
You’re very welcome 🙂 Thank you
Hi Derek!
Awesome learning experience for me thanks to you!!
Could you tell if you are planning to do tutorials on headless web scrapping in java?
Thanks!!
Thank you 🙂 I have a bunch of JSON and XML scrapping tutorials later in this series and in my Android tutorials