I have a rss feed reader application. The goal is to store the title and image for each item in a custom object named RSSItem, and oll the RSSItem objects in another object named RSSFeed. The problem is that if an item element does not have an enclosure element SaxException is thrown. How should I handle the errors with this parser? Here is the parser code:
public class Parser {
private final String RSS_ELEMENT = "rss";
private final String CHANNEL_ELEMENT = "channel";
private final String ITEM_ELEMENT = "item";
private final String ENCLOSURE_ELEMENT = "enclosure";
private final String TITLE_ELEMENT = "title";
private final String URL_ATTRIBUTE = "url";
private final String TYPE_ATTRIBUTE = "type";
private final String IMAGE_TYPE = "image/jpeg";
RSSItem rssItem;
RSSFeed rssFeed;
final URL mFeedUrl;
public Parser(String feedUrl) {
try {
mFeedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
Log.e(e.getClass().getSimpleName(), e.getMessage());
throw new RuntimeException(e);
}
rssFeed = new RSSFeed();
}
protected InputStream getInputStream() {
try {
return mFeedUrl.openConnection().getInputStream();
} catch (IOException e) {
Log.e(e.getClass().getSimpleName(), e.getMessage());
return null;
}
}
public RSSFeed parse() {
InputStream istream = getInputStream();
RootElement root = new RootElement(RSS_ELEMENT);
Element channel = root.requireChild(CHANNEL_ELEMENT);
Element itemElement = channel.requireChild(ITEM_ELEMENT);
Element enclosure = itemElement.requireChild(ENCLOSURE_ELEMENT);
Element title = itemElement.requireChild(TITLE_ELEMENT);
enclosure.setStartElementListener(new StartElementListener() {
public void start(Attributes attrs) {
String imageType = attrs.getValue(TYPE_ATTRIBUTE);
if (imageType.equals(IMAGE_TYPE)) {
try {
String imageUrl = attrs.getValue(URL_ATTRIBUTE);
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
rssItem.setImage(bitmap);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
title.setEndTextElementListener(new EndTextElementListener() {
public void end(String body) {
rssItem.setTitle(body);
}
});
itemElement.setStartElementListener(new StartElementListener() {
public void start(Attributes arg0) {
rssItem = new RSSItem();
}
});
itemElement.setEndElementListener(new EndElementListener() {
public void end() {
rssFeed.addItem(rssItem);
}
});
try {
Xml.parse(istream, Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
e.printStackTrace();
}
return rssFeed;
}
}
I would not recommend trying to implement your own RSS parser , but rather using a standard library for that.
It's fairly easy to setup an implementation of a SAX parser but the hard part is to be able to parse any and every feed under the sun.
You need to cater to all formats RSS 1, RSS 2, Atom etc. Even then you will have to contend with poorly formatted feeds.
I had faced similar problems in the past so decided to do my feed parsing on a server and just get the parsed contents. This allows me to run more complex libraries and parser which I can modify without pushing out updates for my app.
I have the following service running on AppEngine which allows for a much simpler XML / JSON parsing at your end. There is a fixed and simple structure to the response. You can use this for parsing
http://evecal.appspot.com/feedParser
You can send both POST and GET requests with the following parameters.
feedLink : The URL of the RSS feed response : JSON or XML as the response format
Examples:
For a POST request
curl --data-urlencode "feedLink=http://feeds.bbci.co.uk/news/world/rss.xml" --data-urlencode "response=json" http://evecal.appspot.com/feedParser
For GET request
evecal.appspot.com/feedParser?feedLink=http://feeds.nytimes.com/nyt/rss/HomePage&response=xml
My android app "NewsSpeak" uses this too.
Related
i have this code that warks perfectly
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
#Override
public void onReceivedData(byte[] arg0) {
String data = null;
try {
data = new String(arg0, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
tvAppend(textView, data);
}
};
I'm trying to substring the string data and display it to textView but my app crashes. I don't know why. Its about encoding of data string?
There might be a case when the byte[] to String conversion fails.
I would suggest you replace
String data = null;
to
String data = "";
Also add the crash log.
I have a problem populating separate TextView with the content from the same JSON.
Each fragment is having a ListView populated by adapter. Data is pulled from JSON file. First, I am importing data from JSONArray and adding it to object Article created separately:
JSONObject e = articlesJsonResponse.getJSONObject(i);
String title = e.getString("title");
int itemId = e.getInt("id");
Article article = new Article(title, itemId);
articles.add(article);
Then, I have created ArticleAdapter where I am putting this content into ListView. This works.
In my Activity, I am then creating a list out of that:
ListView mainListView = (ListView) findViewById(R.id.main_list);
mAdapter = new ArticleAdapter (getActivity(), new ArrayList<Article>());
mainListView.setAdapter(mAdapter);
Now, I would like to create a TextView in the same activity, which would pull "title" from the first object Article in the list.
TextView featuredImageTitle = (TextView) findViewById(R.id.featuredimage_title);
featuredImageTitle.setText(??????????);
Should I pass this info from adapter? Or from Article object? Or should I read it from the 0 position in the list I have built for the ListView?
Here is my full code which imports the content and creates the object.
public final class QueryUtils {
public QueryUtils() {
}
// Returns new URL object from the URL String
private static URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Problem building URL", e);
}
return url;
}
// makes a HTTP request to the URL and returns String
private static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving articles JSON.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// Closing the input stream could throw an IOException, which is why
// the makeHttpRequest(URL url) method signature specifies than an IOException
// could be thrown.
inputStream.close();
}
}
return jsonResponse;
}
// Query the JSON info and return a list of {#link Article} objects.
public static List<Article> extractArticles(String requestUrl) {
// Create URL object
URL url = createUrl(requestUrl);
// Perform HTTP request to the URL and receive a JSON response back
String jsonResponse = null;
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
Log.e(LOG_TAG, "Problem making the HTTP request.", e);
}
List<Article> articles = extractFromJson(jsonResponse);
// Return the list of articles
return articles;
}
/**
* Convert the {#link InputStream} into a String which contains the
* whole JSON response from the server.
*/
private static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
/**
* Return a list of {#link Article} objects that has been built up from
* parsing a JSON response.
*/
public static List<Article> extractFromJson(String articleJSON) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(articleJSON)) {
return null;
}
// Create an empty ArrayList that we can start adding earthquakes to
List<Article> articles = new ArrayList<>();
// Try to parse JSON response. If there's a problem with the way the JSON
// is formatted, a JSONException exception object will be thrown.
// Catch the exception so the app doesn't crash, and print the error message to the logs.
try {
// Create a JSONArray from the JSON response string
JSONArray articlesJsonResponse = new JSONArray(articleJSON);
// For each article in the articleArray, create an Article object
for (int i=0; i < articlesJsonResponse.length(); i++) {
// Parse the response given by the json string and
// build up a list of article objects with the corresponding data.
JSONObject e = articlesJsonResponse.getJSONObject(i);
String title = e.getString("title");
int articleId = e.getInt("id");
int views = e.getInt("views");
int comments = e.getInt("comments");
String thumb = e.getString("image");
String url = e.getString("url");
String date = e.getString("date");
Article article = new Article(title, articleId, views, comments, thumb, url, date);
articles.add(article);
}
} catch (JSONException e) {
// If an error is thrown when executing any of the above statements in the "try" block,
// catch the exception here, so the app doesn't crash. Print a log message
// with the message from the exception.
Log.e("QueryUtils", "Problem parsing JSON results", e);
}
// Return the list of articles
return articles;
}
}
If you need to access only the first object title on the list
get the 0 positions of your list but also check if list size > 0 to not give Index exception
like
if(articles.size > 0){
featuredImageTitle.setText(articles.get(0).getTitle)
}
but if you need to get the title from the clicked object in the list you need to implement OnItemClickListener to you listView
mainListView.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
{
featuredImageTitle.setText(articles.get(position).getTitle);
}
and be sure to set android:descendantFocusability="blocksDescendants" on the first parent layout inside the list
Im loading data (url) from a json file to a WebView (with gson). When i load the data from a different Activity through a static variable (WebView) i get the 12th url entry of my JSON file. When im loading the data to a inner WebView of my Activity i get the 1st url like it should be.
OtherActivity.mWebView1.loadUrl(JsonData.getUrl()); --> here i get the 12th url
mWebView2.loadUrl(JsonData.getUrl()); --> here i get the 1st url
They both use the same method to load the Data from the JSON file (gson):
#SerializedName("url")
#Expose
private String url;
public String getUrl() {return url;}
public void setUrl(String url) {
this.url = url;
}
Here my LoadJsonFromAsset class:
public class SwipeUtils {
public static List<AdInfo> loadProfiles(Context context){
try{
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
JSONArray array = new JSONArray(loadJSONFromAsset(context, "adInfo.json"));
List<AdInfo> adInfoList = new ArrayList<>();
adInfoList.indexOf("");
for(int i=0;i<array.length();i++){
AdInfo adInfo = gson.fromJson(array.getString(i), AdInfo.class);
adInfoList.add(adInfo);
Log.d("test",adInfo.toString());
}
return adInfoList;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
private static String loadJSONFromAsset(Context context, String jsonFileName) {
String json = null;
InputStream is=null;
try {
AssetManager manager = context.getAssets();
Log.d(TAG,"path "+jsonFileName);
is = manager.open(jsonFileName);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
return json;
}
}
The problem was the method where i set the loadUrl(). It was in a loop an in the time where the loadUrl() worked it was already at the 12th entry.
I'm new to Android and using web APIs, and I'm writing an Android App that scans a barcode from a book and then search its ISBN in Google Books API.
I have this url after the barcode scan: https://www.googleapis.com/books/v1/volumes?q=isbn:9788432250651&AIzaSyCpYez5556X4UzPV6rF4kkspj9DsCs_Q_c
And the next code:
private class GetBookInfo extends AsyncTask <View, Void, Integer> {
#Override
protected Integer doInBackground(View... urls) {
// make Call to the url
makeCall("https://www.googleapis.com/books/v1/volumes?" +
"q=isbn:" + ean_content + "&AIzaSyCpYez5556X4UzPV6rF4kkspj9DsCs_Q_c");
//print the call in the console
System.out.println("https://www.googleapis.com/books/v1/volumes?" +
"q=isbn:" + ean_content + "&AIzaSyCpYez5556X4UzPV6rF4kkspj9DsCs_Q_c");
return null;
}
#Override
protected void onPreExecute() {
// we can start a progress bar here
}
#Override
protected void onPostExecute(Integer result) {
String ruta = save_cover(getApplicationContext(), title, book_cover);
Intent intent = new Intent(MainActivity.this, Spreadsheets.class);
// intent.putExtra(title,title);
// intent.putExtra(author,authors);
// intent.putExtra(date,date);
// intent.putExtra(category,categories);
// intent.putExtra(description,description);
//finish();
startActivity(intent);
finish();
}
}
public void makeCall(String stringURL) {
URL url = null;
BufferedInputStream is = null;
JsonReader jsonReader;
try {
url = new URL(stringURL);
} catch (Exception ex) {
System.out.println("Malformed URL");
}
try {
if (url != null) {
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
is = new BufferedInputStream(urlConnection.getInputStream());
}
} catch (IOException ioe) {
System.out.println("IOException");
}
if (is != null) {
try {
jsonReader = new JsonReader(new InputStreamReader(is, "UTF-8"));
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
if (name.equals("title")) {
title = jsonReader.nextString();
}
else if (name.equals("authors")) {
authors = jsonReader.nextString();
}
else if (name.equals("publishedDate")) {
date = jsonReader.nextString();
}
else if (name.equals("categories")) {
categories = jsonReader.nextString();
}
else if (name.equals("description")) {
description = jsonReader.nextString();
}
// else if (name.equals("averageRating")) {
// rating = jsonReader.nextString();
// }
else if (name.equals("thumbnail")) {
image = jsonReader.nextString();
book_cover = download_cover(image);
}
else {
jsonReader.skipValue();
}
}
jsonReader.endObject();
}
catch (Exception e) {
System.out.println("Exception");
}
}
}
This isn't retrieving anything from the API. I would appreciate your help, thank you!
I think what you need to do next is request a connection from the API, open the connection, using JSON retrieve data from the API and use the inputStream to get the data stored in an array.
something like :Implement these methods in a class:
private static String makeHttpRequest(URL url) throws IOException
private static String readFromStream(InputStream inputStream) throws IOException
private static List extractFeatureFromJson(String booksJson)
public static List featchBookData(String requestUrl)
Here is a full code example of how to use Google Books API in Android with Feign or Retrofit. These libraries provide a higher level abstraction on top of HTTP so that you can use simple method calls and objects in your code, instead of messing with requests, responses and JSON deserialization.
i am creating an android app which fetches information from rss feeds...till now i can successfully parsing a single rss feed...and display whatever i need.
I want to parse multiple RSS feeds and filter it based on the tags given on those sites...most of the rss will be feedburner rss.
Is there a way to combine many rss feeds filter it based on tags,keywords etc..... and create a single rss feed
public class BaseFeedParser {
static String feedUrlString = "http://feeds.dzone.com/dzone/frontpage";
// names of the XML tags
static final String RSS = "rss";
static final String CHANNEL = "channel";
static final String ITEM = "item";
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
private final URL feedUrl;
protected BaseFeedParser(){
try {
this.feedUrl = new URL(feedUrlString);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public List<Message> parse() {
final Message currentMessage = new Message();
RootElement root = new RootElement(RSS);
final List<Message> messages = new ArrayList<Message>();
Element itemlist = root.getChild(CHANNEL);
Element item = itemlist.getChild(ITEM);
item.setEndElementListener(new EndElementListener(){
public void end() {
messages.add(currentMessage.copy());
}
});
item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setTitle(body);
}
});
item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setLink(body);
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setDescription(body);
}
});
item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setDate(body);
}
});
try {
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
throw new RuntimeException(e);
}
return messages;
}
}
You can do this non-programmatically using Yahoo Pipes - it allows you to "pipe", filter and aggregate RSS data into a single feed.