Android SAXParser, parse into array and get child nodes - java

I'm working on a small app that uses and xml file to print an ArrayList of chapters which in turn points to a specific html file.
I used this tutorial to get me started: http://www.anddev.org/novice-tutorials-f8/parsing-xml-from-the-net-using-the-saxparser-t353.html
My xml file looks something like this:
<chapters>
<chapter title="Förutsättningar">
<page title="Sida 3" url="sida_3.html" />
<page title="Sida 4" url="sida_4.html" />
</chapter>
</chapters>
Using the tutorial above I've managed to output each chapter node into an ArrayList with a onListItemClick function on each item. So far so good.
The problem I'm having is that I can't figure out how to get a specific child node and load the html file when I click an item. I'm pretty new to Android.
Any ideas? I would really appreciate ANY help on the subject.
Here's my source:
ParsingXML.java
public class ParsingXML extends ListActivity {
private final String MY_DEBUG_TAG = "XmlParser";
public String lang = null;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setTitle("Lastsäkring");
Bundle bundle = this.getIntent().getExtras();
lang = bundle.getString("lang");
Log.i("ParsingXML", "Chosen language: " + this.lang + ", Type: " + this.lang.getClass().getName());
TextView tv = new TextView(this);
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
ExampleHandler myExampleHandler = new ExampleHandler();
xr.setContentHandler(myExampleHandler);
/*
* If XML-file is located online (needs internet permissions in the manifest):
* URL url = new URL("http://dev.houdini.se/android/demo.xml");
* xr.parse(new InputSource(url.openStream()));
*/
if(this.lang.equals("en"))
xr.parse(new InputSource(this.getResources().openRawResource(R.raw.en_content)));
else
xr.parse(new InputSource(this.getResources().openRawResource(R.raw.sv_content)));
ParsedExampleDataSet parsedExampleDataSet = myExampleHandler.getParsedData();
this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, parsedExampleDataSet.toArrayList()));
} catch(Exception e) {
tv.setText("Error: " + e.getMessage());
Log.e(MY_DEBUG_TAG, "XmlParseError", e);
this.setContentView(tv);
}
}
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Context context = getApplicationContext();
int duration = Toast.LENGTH_SHORT;
CharSequence text = "Clicked position: " + position + ", id: " + id;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
/*switch( position )
{
case 0:
Bundle bundle = new Bundle();
bundle.putString("WindowTitle", "TESTA");
Intent intent = new Intent(this, TextPage.class);
intent.putExtras(bundle);
startActivity(intent);
break;
case 1:
Intent video = new Intent(this, Video.class);
startActivity(video);
break;
case 2:
Intent swipe = new Intent(this, Swipe.class);
startActivity(swipe);
break;
}*/
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.settings:
Intent prefsActivity = new Intent(getBaseContext(), Preferences.class);
startActivity(prefsActivity);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
ExampleHandler.java
public class ExampleHandler extends DefaultHandler {
private boolean in_chapters = false;
private boolean in_chapter = false;
private boolean in_page = false;
private ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();
public ParsedExampleDataSet getParsedData() {
return this.myParsedExampleDataSet;
}
#Override
public void startDocument() throws SAXException {
this.myParsedExampleDataSet = new ParsedExampleDataSet();
}
#Override
public void endDocument() throws SAXException {
// Nothing to do
}
#Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
if(localName.equals("chapters")) {
this.in_chapters = true;
} else if(localName.equals("chapter")) {
this.in_chapter = true;
String attrValue = atts.getValue("title");
myParsedExampleDataSet.setExtractedString(attrValue);
} else if(localName.equals("page")) {
this.in_page = true;
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if(localName.equals("chapters")) {
this.in_chapters = false;
} else if(localName.equals("chapter")) {
this.in_chapter = false;
} else if(localName.equals("page")) {
this.in_page = false;
}
}
#Override
public void characters(char ch[], int start, int length) {
if(this.in_page == true) {
myParsedExampleDataSet.setExtractedString(new String(ch, start, length));
}
}
}
ParsedExampleDataSet.java
public class ParsedExampleDataSet {
private String extractedString = "";
private ArrayList<String> myArr = new ArrayList<String>();
private int extractedInt = 0;
public ArrayList<String> getExtractedString() {
//return extractedString; Function Type = String
return myArr;
}
public void setExtractedString(String extractedString) {
//this.extractedString += extractedString + "\n";
myArr.add(extractedString);
}
public int getExtractedInt() {
return extractedInt;
}
public void setExtractedInt(int extractedInt) {
this.extractedInt = extractedInt;
}
public String toString() {
return "NODER\n" + this.extractedString;
}
public ArrayList<String> toArrayList() {
return this.myArr;
}
}

First create proper data structure:
public class PageNode {
public String title;
public String url;
/* Getters/setter/constructor etc. if you feel like*/
public String toString() {
return title;
}
}
public class ChapterNode {
public String title;
public ArrayList<PageNode> pages = new ArrayList<PageNode>();
/* Getters/setter/constructor etc. if you feel like*/
}
And parse the xml accordingly. Example:
ArrayList<ChapterNode> chapters = new ArrayList<ChapterNode>();
ChapterNode chapterNode = null;
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
if(localName.equals("chapters")) {
} else if(localName.equals("chapter")) {
chapterNode = new ChapterNode();
chapterNode.title = atts.getValue("title");
} else if(localName.equals("page")) {
PageNode pageNode = new PageNode();
pageNode.title = atts.getValue("title");
pageNode.url = atts.getValue("url");
chapterNode.pages.add(pageNode);
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if(localName.equals("chapters")) {
} else if(localName.equals("chapter")) {
chapters.add(chapterNode);
chapterNode = null;
} else if(localName.equals("page")) {
}
}
Then you can access the pageNode like this:
PageNode pageNode = chapterNode.pages.get(position);
And set adapter like this:
this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, chapterNode.pages));

You have to check for boolean variables while chapter tag is true you have to add pages in one arraylist and when chapter tag is false you have to add that arraylist in another gloabl arraylist

(Without having looked at the example tutorial...)
Have a look at the Attributes parameter of startElement in your example handler. It should contain a value for "url" (it looks like you're only getting the value for "title").

I'm used to using DocumentBuilderFactory, so my solution is:
firstly, you should create ArrayHelper class like this:
public class ArrayHelper {
public static ArrayList<HashMap<String, ?>> list = new ArrayList<HashMap<String, ?>>();
}
than:
public class CoversParseTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onPreExecute() {
}
#Override
protected Boolean doInBackground(Void ... arg0) {
try {
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
document = dBuilder.parse(new InputSource(this.getResources().openRawResource(R.raw.en_content)));
document.getDocumentElement().normalize();
NodeList nodeListIssue = document.getElementsByTagName("page");
for (int i = 0; i < nodeListIssue.getLength(); i++) {
HashMap<String, Object> temp = new HashMap<String, Object>();
Node node = nodeListIssue.item(i);
Element elementMain = (Element) node;
String pageID = elementMain.getAttribute("title");
String issueID = elementMain.getAttribute("url");
temp.put("title", pageID);
temp.put("url", issueID);
ArrayHelper.list.add(temp);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
};
return false;
}
#Override
protected void onPostExecute(Boolean result) {
//what happend if done.
}
}
and execute this class like this:
new CoversParseTask().execute();
now we must create simple adapter:
SimpleAdapter adapter = new MySimpleAdapter(this, selectLastSearch(), R.layout.custom_row_view, new String[] { "Title", "Url" }, new int[] { R.id.title, R.id.url});
and our MySimpleAdapter looks like this:
public class MySimpleAdapter extends SimpleAdapter {
Context localcontext = null;
public MySimpleAdapter(Context context,List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
localcontext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
return view;
}
}
noe set adapter to listview:
listview.setAdapter(adapter);
if You want to get URL from list, you should add listner to listview like this:
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view,
int position, long arg) {
Log.v("URL", ArrayHelper.list.get(position).get("url").toString());
}
});
and thats all, i hope that i help you :)

Related

listview doesn't change and keeps the same items

i have listview that changes according to the number i type in edittext, the list doesn't change when i type another number and keeps the same items from the previous number typed.
here is the adapter:
public class ElectorListAdapter extends BaseAdapter{
private Context activity;
private LayoutInflater inflater;
private List<Electors> DataList;
private ArrayList<Electors> arraylist=null;
// private ItemFilter mFilter = new ItemFilter();
public ElectorListAdapter(Context activity, List<Electors> electors) {
this.activity = activity;
this.DataList = electors;
this.arraylist = new ArrayList<Electors>();
this.arraylist.addAll(electors);
inflater = LayoutInflater.from(activity);
}
#Override
public int getCount() {
return DataList.size();
}
#Override
public Object getItem(int location) {
return DataList.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.elector_info_cell_list, null);
TextView name = (TextView)convertView.findViewById(R.id.name);
TextView status = (TextView)convertView.findViewById(R.id.status);
Electors m = DataList.get(position);
//97697691
name.setText(m.getName());
status.setText(m.getStatus().toString());
return convertView;
}
}
and here is the implantation in the MainActivity:
adapter = new ElectorListAdapter(this, list);
lv.setAdapter(adapter);
lv.setTextFilterEnabled(true);
and here where i clear the list:
serial.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
serialno = serial.getText().toString();
if(serial.getText()!=null){
//list = new ArrayList<>();
list.clear();
getlist();
}else if(serial.getText()==null){
lv.setVisibility(v.GONE);
}
}
}
});
here is the getlist();
public void getlist(){
//list = new ArrayList<>();
try {
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
String URL = "http://gickuwait-dev.com/electionapi/api/electors";
JSONObject jsonBody = new JSONObject();
// jsonBody.put("tblRegisteredUsers_nickName", username.getText().toString().trim());
jsonBody.put("SerialNo", serialno.toString().trim());
final String requestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//my response later should be changed
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
})
{
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString;
String json = null;
try {
json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
responseString = String.valueOf(json).trim();
ArrayList<ElectorResponse> list_response = new ArrayList<ElectorResponse>();
Type listType = new TypeToken<List<ElectorResponse>>() {}.getType();
list_response = new Gson().fromJson(responseString, listType);
for (int i = 0; i < list_response.size(); i++) {
Electors listItemData = new Electors();
listItemData.setName(list_response.get(i).getNameAr());
listItemData.setStatus(list_response.get(i).getExpr1());
listItemData.setId(list_response.get(i).getPKID());
if (listItemData.getName().startsWith(classletter)){
list.add(listItemData);
}
}
// i should have this piece of code for methods that are running in the background
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
// String Check = yourModel.getMessagetitle();
return Response.success(list_response.toString(), HttpHeaderParser.parseCacheHeaders(response));
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
here where i use filter to filter the list
name.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable theWatchedText) {
//Vote.this.adapter.getFilter().filter(theWatchedText.toString());
String text = name.getText().toString().toLowerCase(Locale.getDefault());
// Vote.this.adapter.getFilter().filter(text);
search_model(name.getText().toString());
}
});
private void search_model(String key){
search = new ArrayList<>();
for(int i = 0;i<list.size();i++){
Electors electors = list.get(i);
if(electors.getName().toLowerCase(Locale.getDefault()).startsWith(key)){
search.add(electors);
}
}
adapter = new ElectorListAdapter(this, search);
lv.setAdapter(adapter);
lv.setTextFilterEnabled(true);
}
how can i make it change its values when i type another number, is there something missing in the adapter? thanks in advance
You need to notify the list of changes to the dataset via notifyDatasetChanged()
you should have clear array list when data is changed. Then add your new text to the array list and update it.
arraylist.clear(); //to clear array list
arraylist.add(); //to add new text
adapter.notifyDataSetChanged(); //to notify adapter
if(serial.getText()!=null){
//list = new ArrayList<>();
list.clear();
// since you removed the item you need to inform the adapter to
//refresh view
adapter.notifyDataSetChanged();
// also as soon as getlist(); gets new list , set that list on adapter and call
// adapter.notifyDataSetChanged();
getlist();
}

Open Navigator after clicked on a Rss Reader

i have a news reader (using rss), it's work as well, now i'm trying to open the navigator after clicked on a news, but i don't know how to get the link (i just know that i have to use getLink() but i don't know where):
Actualites.java
public class Actualites extends android.support.v4.app.Fragment{
AsyncTask<Void, Void, List> a = null;
NewsAdapter adapter = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.activity_actualites, container, false);
ListView list = (ListView) view.findViewById(R.id.listView1);
adapter = new NewsAdapter(getActivity(), new ArrayList<News>());
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("http://www.solutis.fr")));
}
});
a = new AsyncTask<Void, Void, List>() {
#Override
protected List doInBackground(Void... params) {
ArrayList<News> res = new ArrayList<News>();
try {
URL url = new URL("http://www.solutis.fr/actualites-rachat-credit,rss.html?format=feed");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
RssParser parser = new RssParser();
try {
return parser.parse(urlConnection.getInputStream());
} catch (XmlPullParserException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return res;
}
#Override
protected void onPostExecute(List result) {
adapter.update(result);
}
};
a.execute();
TextView textView =(TextView)getActivity().findViewById(R.id.main_toolbar_title);
textView.setText(getString(R.string.title_actu));
textView.setTypeface(Typeface.createFromAsset(getActivity().getAssets(), "fonts/GothamBook.ttf"));
return view;
}
}
NewsAdapter.java
public class NewsAdapter extends BaseAdapter {
List<News> news;
Context context;
public NewsAdapter(Context context, List<News> news) {
this.news = news;
this.context = context;
}
public void update(List<News> news) {
this.news = news;
notifyDataSetChanged();
}
#Override
public int getCount() {
return news.size();
}
#Override
public Object getItem(int arg0) {
return news.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
LayoutInflater li = LayoutInflater.from(context);
View v = li.inflate(R.layout.three_line_list_item, null);
TextView tv1 = (TextView)v.findViewById(android.R.id.text1);
tv1.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/GothamBold.ttf"));
tv1.setTextSize(15);
TextView tv3 = (TextView)v.findViewById(android.R.id.title);
tv3.setTextColor(Color.parseColor("#2B729F"));
tv3.setTextSize(13);
tv3.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/GothamBook.ttf"));
TextView tv2 = (TextView)v.findViewById(android.R.id.text2);
tv2.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/GothamBook.ttf"));
tv2.setTextSize(14);
News n = (News)getItem(arg0);
tv1.setText(n.getTitle());
String pubDate = Html.fromHtml(n.getPubDate()).toString().replace((char) 65532, (char) 32).trim();
tv3.setText(pubDate);
String content = Html.fromHtml(n.getContent()).toString().replace((char) 65532, (char) 32).trim();
tv2.setText(content);
return v;
}
}
RssParser.java
public class RssParser {
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
private static final String ns = null;
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
public ArrayList<News> parse(InputStream in) throws XmlPullParserException, IOException {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(in, null);
parser.nextTag();
ArrayList<News> entries = new ArrayList<News>();
parser.require(XmlPullParser.START_TAG, ns, "rss");
parser.nextTag();
parser.require(XmlPullParser.START_TAG, ns, "channel");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("item")) {
String title = "";
String link = "";
String pubDate = "";
String content = "";
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
name = parser.getName();
if (name.equals("title")) {
title = readText(parser);
} else if (name.equals("link")) {
link = readText(parser);
} else if (name.equals("pubDate")) {
pubDate = readText(parser);
} else if (name.equals("description")) {
content = readText(parser);
} else
skip(parser);
}
entries.add(new News(title, pubDate, content));
} else
skip(parser);
}
return entries;
}
}
News.java
public class News {
private String title;
private String content;
private String pubDate;
private String link;
public News(String title, String pubDate, String content) {
this.title = title;
this.content = content;
this.pubDate = pubDate;
}
public News(String link, String title, String pubDate, String content) {
this.link = link;
this.title = title;
this.content = content;
this.pubDate = pubDate;
}
public String getTitle() {
return (title);
}
public String getContent() {
return (content);
}
public String getPubDate(){
return (pubDate);
}
public String getLink(){
return (link);
}
}
I have to change public void onItemClick(), i've just put a url, but i have to get the url of the news, but i don't know how to do that. Someone can help me ?
You can get the news object from the adapter using the position parameter in the onItemClick. I haven't tested the code but it will be something like the following;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
News news = (News) adapter.getItem(position)
startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(news.getLink())));
}

Type mismatch: cannot convert from String to List<Cmd>

I'm getting the follwoing error:
Type mismatch: cannot convert from String to List
on the line this.videos = videos; from the following code:
public void setVideos(String videos) {
this.videos = videos;
}
I've tried following both of Eclipse's suggestions:
Change type of videos to string
Change type of videos to List
However, neither seems to resolve the issue and both cause additonal errors.
I'm not sure exactly what I can do to resolve the issue at this point.
Cmd.java
public class Cmd implements ListAdapter {
private String success;
private String cmd;
List<Cmd> videos;
private String video;
private String numberofvideos;
private String videoname;
private String videourl;
private LayoutInflater mInflater;
Button fav_up_btn1;
Button fav_dwn_btn1;
Context my_context;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_user_video,
parent, false);
}
ImageView thumb = (ImageView) convertView
.findViewById(R.id.userVideoThumbImageView);
TextView title = (TextView) convertView
.findViewById(R.id.userVideoTitleTextView);
TextView uploader = (TextView) convertView
.findViewById(R.id.userVideouploaderTextView);
TextView viewCount = (TextView) convertView
.findViewById(R.id.userVideoviewsTextView);
uploader.setText(videos.get(position).getTitle());
viewCount.setText(videos.get(position).getviewCount() + " views");
// Get a single video from our list
final Cmd video = videos.get(position);
// Set the image for the list item
// Set the title for the list item
title.setText(video.getTitle());
uploader.setText("by " + video.getUploader() + " | ");
return convertView;
}
public String getUploader() {
// TODO Auto-generated method stub
return null;
}
public String getviewCount() {
// TODO Auto-generated method stub
return null;
}
public CharSequence getTitle() {
// TODO Auto-generated method stub
return null;
}
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getNumberOfVideos() {
return numberofvideos;
}
public void setNumberOfVideos(String numberofvideos) {
this.numberofvideos = numberofvideos;
}
public List<Cmd> getVideos() {
return videos;
}
public void setVideos(String videos) {
this.videos = videos;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
public String getVideoName() {
return videoname;
}
public void setVideoName(String videoname) {
this.videoname = videoname;
}
public String getVideoURL() {
return videourl;
}
public void setVideoURL(String videourl) {
this.videourl = videourl;
}
#Override
public int getCount() {
return videos.size();
}
#Override
public Object getItem(int position) {
return videos.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
}
SAXXMLHandler.java
public class SAXXMLHandler extends DefaultHandler {
private List<Cmd> videos;
private String tempVal;
// to maintain context
private Cmd cmd;
public SAXXMLHandler() {
videos = new ArrayList<Cmd>();
}
public List<Cmd> getResponse() {
return videos;
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// reset
tempVal = "";
if (qName.equalsIgnoreCase("cmd")) {
// create a new instance of cmd
cmd = new Cmd();
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("videos")) {
// add it to the list
videos.add(cmd);
} else if (qName.equalsIgnoreCase("success")) {
cmd.setSuccess(tempVal);
} else if (qName.equalsIgnoreCase("numberofvideos")) {
cmd.setNumberOfVideos(tempVal);
} else if (qName.equalsIgnoreCase("videos")) {
cmd.setVideos(tempVal);
} else if (qName.equalsIgnoreCase("video")) {
cmd.setVideo(tempVal);
} else if (qName.equalsIgnoreCase("videoname")) {
cmd.setVideoName(tempVal);
} else if (qName.equalsIgnoreCase("videourl")) {
cmd.setVideoURL(tempVal);
}
}
}
Update the setter method for variable List<Cmd> videos as below :
public void setVideos(List<Cmd> videos) {
this.videos = videos;
}
setVideos(String videos) should be defined as setVideos(List<Cmd> videos)

Android / Java - ListView Populated with XML Data Using ArrayList: Only Displays First Item

I'm attempting to populate a ListView with XML Data by using an ArrayList - which I've been able to accomplish thus far - the issue is the ArrayList does not seem to populate the ListView with data beyond the first item in the listView and I'm unsure why.
Screenshot
XML Data:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<response>
<cmd>getVideos</cmd>
<success>1</success>
<NumberOfVideos>4</NumberOfVideos>
<Videos>
<Video>
<VideoName>sample_iPod</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/06087297988b.m4v
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_mpeg4</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/b5ed9e7100e2.mp4
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_sorenson</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/2a8e64b24997.mov
</VideoUrl>
<VideoTags/>
</Video>
<Video>
<VideoName>sample_iTunes</VideoName>
<VideoDesc/>
<VideoUrl>
http://mobile.example.com/api/wp-content/uploads/sites/6/2014/01/api/1/6c7f65254aad.mov
</VideoUrl>
<VideoTags/>
</Video>
</Videos>
</response>
CustomListViewAdapter.java
public class CustomListViewAdapter extends ArrayAdapter<Cmd> {
Activity context;
List<Cmd> videos;
public CustomListViewAdapter(Activity context, List<Cmd> videos) {
super(context, R.layout.list_item2, videos);
this.context = context;
this.videos = videos;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtSuccess;
TextView txtCmd;
TextView txtPrice;
}
public Cmd getItem(int position) {
return videos.get(position);
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item2, null);
holder = new ViewHolder();
holder.txtSuccess = (TextView) convertView.findViewById(R.id.success);
holder.txtCmd = (TextView) convertView.findViewById(R.id.cmd);
holder.txtPrice = (TextView) convertView.findViewById(R.id.price);
holder.imageView = (ImageView) convertView.findViewById(R.id.thumbnail);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Cmd cmd = (Cmd) getItem(position);
holder.txtSuccess.setText(cmd.getSuccess());
holder.txtCmd.setText(cmd.getCmd());
// holder.imageView.setImageBitmap(cmd.getImageBitmap());
holder.txtPrice.setText(cmd.getVideoName() + "");
return convertView;
}
}
SAXParserAsyncTaskActivity.java
public class SAXParserAsyncTaskActivity extends Activity implements
OnClickListener, OnItemClickListener {
Button button;
ListView listView;
List<Cmd> videos = new ArrayList<Cmd>();
CustomListViewAdapter listViewAdapter;
static final String URL = "http://mobile.example.com/api/xml.php?cmd=getVideos&username=fake&password=";
public static final String LIBRARY = "Library";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.parser_main);
findViewsById();
button.setOnClickListener(this);
listView.setOnItemClickListener(this);
GetXMLTask task = new GetXMLTask(this);
task.execute(new String[] { URL });
}
private void findViewsById() {
button = (Button) findViewById(R.id.button);
listView = (ListView) findViewById(R.id.cmdList);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
#Override
public void onClick(View view) {
// GetXMLTask task = new GetXMLTask(this);
// task.execute(new String[] { URL });
}
// private inner class extending AsyncTask
private class GetXMLTask extends AsyncTask<String, Void, List<Cmd>> {
private Activity context;
public GetXMLTask(Activity context) {
this.context = context;
}
protected void onPostExecute(List<Cmd> videos) {
listViewAdapter = new CustomListViewAdapter(context, videos);
listView.setAdapter(listViewAdapter);
}
/*
* uses HttpURLConnection to make Http request from Android to download
* the XML file
*/
private String getXmlFromUrl(String urlString) {
StringBuffer output = new StringBuffer("");
try {
InputStream stream = null;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("GET");
httpConnection.connect();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
stream = httpConnection.getInputStream();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(stream));
String s = "";
while ((s = buffer.readLine()) != null)
output.append(s);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return output.toString();
}
#Override
protected List<Cmd> doInBackground(String... urls) {
List<Cmd> videos = null;
String xml = null;
for (String url : urls) {
xml = getXmlFromUrl(url);
InputStream stream = new ByteArrayInputStream(xml.getBytes());
videos = SAXXMLParser.parse(stream);
for (Cmd cmd : videos) {
String videoName = cmd.getVideoName();
// String getVideos = cmd.getVideos();
String getVideo = cmd.getVideo();
String getVideoURL = cmd.getVideoURL();
String getNumberOfVideos = cmd.getNumberOfVideos();
Bitmap bitmap = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1;
try {
bitmap = BitmapFactory.decodeStream(
new URL(videoName).openStream(), null,
bmOptions);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// stream.close();
return videos;
}
}
}
Cmd.java
public class Cmd implements ListAdapter {
private String success;
private String cmd;
List<Cmd> videos;
private String video;
private String numberofvideos;
private String videoname;
private String videourl;
private LayoutInflater mInflater;
Button fav_up_btn1;
Button fav_dwn_btn1;
Context my_context;
// private Bitmap imageBitmap;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If convertView wasn't null it means we have already set it to our
// list_item_user_video so no need to do it again
if (convertView == null) {
// This is the layout we are using for each row in our list
// anything you declare in this layout can then be referenced below
convertView = mInflater.inflate(R.layout.list_item_user_video,
parent, false);
}
// We are using a custom imageview so that we can load images using urls
ImageView thumb = (ImageView) convertView
.findViewById(R.id.userVideoThumbImageView);
//thumb.setScaleType(ScaleType.FIT_XY);
TextView title = (TextView) convertView
.findViewById(R.id.userVideoTitleTextView);
TextView uploader = (TextView) convertView
.findViewById(R.id.userVideouploaderTextView);
TextView viewCount = (TextView) convertView
.findViewById(R.id.userVideoviewsTextView);
uploader.setText(videos.get(position).getTitle());
viewCount.setText(videos.get(position).getviewCount() + " views");
fav_up_btn1 = (Button) convertView.findViewById(R.id.fav_up_btn1);
fav_up_btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
boolean favIsUp = fav_up_btn1
.getBackground()
.getConstantState()
.equals(my_context.getResources()
.getDrawable(R.drawable.fav_up_btn1)
.getConstantState());
// set the background
fav_up_btn1
.setBackgroundResource(favIsUp ? R.drawable.fav_dwn_btn1
: R.drawable.fav_up_btn1);
}
});
// Get a single video from our list
final Cmd video = videos.get(position);
// Set the image for the list item
// / thumb.setImageDrawable(video.getThumbUrl());
//thumb.setScaleType(ScaleType.FIT_XY);
// Set the title for the list item
title.setText(video.getTitle());
uploader.setText("by " + video.getUploader() + " | ");
return convertView;
}
public String getUploader() {
// TODO Auto-generated method stub
return null;
}
public String getviewCount() {
// TODO Auto-generated method stub
return null;
}
public CharSequence getTitle() {
// TODO Auto-generated method stub
return null;
}
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getNumberOfVideos() {
return numberofvideos;
}
public void setNumberOfVideos(String numberofvideos) {
this.numberofvideos = numberofvideos;
}
public List<Cmd> getVideos() {
return videos;
}
public void setVideos(List<Cmd> videos) {
this.videos = videos;
}
public String getVideo() {
return video;
}
public void setVideo(String video) {
this.video = video;
}
public String getVideoName() {
return videoname;
}
public void setVideoName(String videoname) {
this.videoname = videoname;
}
public String getVideoURL() {
return videourl;
}
public void setVideoURL(String videourl) {
this.videourl = videourl;
}
#Override
public int getCount() {
return videos.size();
}
#Override
public Object getItem(int position) {
return videos.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return 0;
}
#Override
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return false;
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public boolean areAllItemsEnabled() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isEnabled(int position) {
// TODO Auto-generated method stub
return false;
}
public String getId() {
// TODO Auto-generated method stub
return null;
}
}
SAXXMLParser.java
public class SAXXMLParser {
public static List<Cmd> parse(InputStream is) {
List<Cmd> response = null;
try {
// create a XMLReader from SAXParser
XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser()
.getXMLReader();
// create a SAXXMLHandler
SAXXMLHandler saxHandler = new SAXXMLHandler();
// store handler in XMLReader
xmlReader.setContentHandler(saxHandler);
// the process starts
xmlReader.parse(new InputSource(is));
// get the `Video list`
response = saxHandler.getResponse();
} catch (Exception ex) {
Log.d("XML", "SAXXMLParser: parse() failed");
ex.printStackTrace();
}
// return video list
return response;
}
}
SAXXMLHandler.java
public class SAXXMLHandler extends DefaultHandler {
private List<Cmd> videos;
private String tempVal;
// to maintain context
private Cmd cmd;
public SAXXMLHandler() {
videos = new ArrayList<Cmd>();
}
public List<Cmd> getResponse() {
return videos;
}
// Event Handlers
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// reset
tempVal = "";
if (qName.equalsIgnoreCase("cmd")) {
// create a new instance of cmd
cmd = new Cmd();
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("videos")) {
// add it to the list
videos.add(cmd);
} else if (qName.equalsIgnoreCase("success")) {
cmd.setSuccess(tempVal);
} else if (qName.equalsIgnoreCase("numberofvideos")) {
cmd.setNumberOfVideos(tempVal);
} else if (qName.equalsIgnoreCase("videos")) {
cmd.setVideos(videos);
} else if (qName.equalsIgnoreCase("video")) {
cmd.setVideo(tempVal);
} else if (qName.equalsIgnoreCase("videoname")) {
cmd.setVideoName(tempVal);
} else if (qName.equalsIgnoreCase("videourl")) {
cmd.setVideoURL(tempVal);
}
}
}
parser_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/button" />
<ListView
android:id="#+id/cmdList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
XML Screenshot
P.S.
If any additional information is required - please let me know (I will be at my desk working on this for the next few hours and will gladly answer any questions and accept any answers promptly)
In SAXXMLHandler.java's endElement() method you only add the cmd to the videos list if qName.equalsIgnoreCase("videos").
In all other cases you modify the cmd but you dont actually add it to the list. You want to add a videos.add(cmd) statement in the else if blocks as well so all the cmd's get added to the list.
This mistake right here is the cause of your List<Cmd> videos only having one item and thus only showing one item in your listview.

extract the images from rss feed

I'm new to android development application and i suppose to parse rss url into a listview. the code is working but we want to extract the images from the rss feed and display it into the listview.
RssItem.java
public class RssItem {
// item title
private String title;
// item link
private String link;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
#Override
public String toString() {
return title;
}
}
ListListener.java
public class ListListener implements OnItemClickListener {
// List item's reference
List<RssItem> listItems;
// Calling activity reference
Activity activity;
public ListListener(List<RssItem> aListItems, Activity anActivity) {
listItems = aListItems;
activity = anActivity;
}
/**
* Start a browser with url from the rss item.
*/
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(listItems.get(pos).getLink()));
activity.startActivity(i);
}
}
RssParseHandler.java
public class RssParseHandler extends DefaultHandler {
private List<RssItem> rssItems;
// Used to reference item while parsing
private RssItem currentItem;
// Parsing title indicator
private boolean parsingTitle;
// Parsing link indicator
private boolean parsingLink;
public RssParseHandler() {
rssItems = new ArrayList<RssItem>();
}
public List<RssItem> getItems() {
return rssItems;
}
#Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
if ("item".equals(qName)) {
currentItem = new RssItem();
} else if ("title".equals(qName)) {
parsingTitle = true;
} else if ("link".equals(qName)) {
parsingLink = true;
}
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("item".equals(qName)) {
rssItems.add(currentItem);
currentItem = null;
} else if ("title".equals(qName)) {
parsingTitle = false;
} else if ("link".equals(qName)) {
parsingLink = false;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (parsingTitle) {
if (currentItem != null)
currentItem.setTitle(new String(ch, start, length));
} else if (parsingLink) {
if (currentItem != null) {
currentItem.setLink(new String(ch, start, length));
parsingLink = false;
}
}
}
}
RssReader.java
public class RssReader {
private String rssUrl;
/**
* Constructor
*
* #param rssUrl
*/
public RssReader(String rssUrl) {
this.rssUrl = rssUrl;
}
/**
* Get RSS items.
*
* #return
*/
public List<RssItem> getItems() throws Exception {
// SAX parse RSS data
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
RssParseHandler handler = new RssParseHandler();
saxParser.parse(rssUrl, handler);
return handler.getItems();
}
}
ITCutiesReaderAppActivity.java
public class ITCutiesReaderAppActivity extends Activity {
// A reference to the local object
private ITCutiesReaderAppActivity local;
/**
* This method creates main application view
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set view
setContentView(R.layout.main);
// Set reference to this activity
local = this;
GetRSSDataTask task = new GetRSSDataTask();
// Start download RSS task
task.execute("http://www.itcuties.com/feed/#sthash.YI6YrEet.dpuf");
// Debug the thread name
Log.d("ITCRssReader", Thread.currentThread().getName());
}
public class GetRSSDataTask extends AsyncTask<String, Void, List<RssItem> > {
#Override
protected List<RssItem> doInBackground(String... urls) {
// Debug the task thread name
Log.d("ITCRssReader", Thread.currentThread().getName());
try {
// Create RSS reader
RssReader rssReader = new RssReader(urls[0]);
// Parse RSS, get items
return rssReader.getItems();
} catch (Exception e) {
Log.e("ITCRssReader", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(List<RssItem> result) {
// Get a ListView from main view
ListView itcItems = (ListView) findViewById(R.id.listMainView1);
// Create a list adapter
ArrayAdapter<RssItem> adapter = new ArrayAdapter<RssItem> (local,android.R.layout.simple_list_item_1, result);
// Set list adapter for the ListView
itcItems.setAdapter(adapter);
// Set list view item click listener
itcItems.setOnItemClickListener(new ListListener(result, local));
}
}
}
After reading online for a few hours I got this, originally the code didn't parse the image but after reading documentation on DOM elements (from the documentation that comes with Android Studio), I was able to create the following code snippet which actually works. I tested it in a console.
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
/**
* Created by user on 7/1/2016.
*/
public class FeedParser {
// names of the XML tags
static final String PUB_DATE = "pubDate";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
static final String IMAGE = "media:thumbnail";
static final String AUTHOR = "author";
final URL feedUrl;
public FeedParser(String feedUrl){
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void parse() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(this.getInputStream());
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName(ITEM);
for (int i=0;i<items.getLength();i++){
Node item = items.item(i);
NodeList properties = item.getChildNodes();
for (int j=0;j<properties.getLength();j++){
Node property = properties.item(j);
String name = property.getNodeName();
if (name.equalsIgnoreCase(TITLE)){
System.out.println(property.getFirstChild().getNodeValue());
} else if (name.equalsIgnoreCase(LINK)){
System.out.println(property.getFirstChild().getNodeValue());
} else if (name.equalsIgnoreCase(AUTHOR)){
StringBuilder text = new StringBuilder();
NodeList chars = property.getChildNodes();
for (int k=0;k<chars.getLength();k++){
text.append(chars.item(k).getNodeValue());
}
System.out.println(text.toString());
} else if (name.equalsIgnoreCase(PUB_DATE)){
System.out.println(property.getFirstChild().getNodeValue());
}
else if (name.equalsIgnoreCase(IMAGE)){
System.out.println(property.getAttributes().getNamedItem("url").getNodeValue());
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] aeg){
new FeedParser("http://www.pcworld.com/index.rss").parse();
}
}
Though my answer is late i hope it helps someone else
You are reinventing the wheel. You can simplify everything by using the android-rss library with droidQuery (originally posted here):
final RSSHandler handler = new RSSHandler(new RSSConfig());
$.ajax(new AjaxOptions().url(options.url())
.type("GET")
.dataType("XML")
.context(this)
.SAXContentHandler(handler)
.success(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
RSSFeed feed = handler.feed();
List<RSSItem> = feed.getItems();
//use this list to update your list adapter, then call the method "getThumbnails()" to get the images associated with the feed item.
}
}));

Categories

Resources