Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge, create tags and put an ascending order the feeds of more RSS Feed links like on Yahoo Pipes?

I need to take the feeds of more RSS Feed urls that I have to aggregate and show the news in descending order.

Some links don't have an xml tag for <category> so I need to create one: I have to know where feeds come from so that I can categorize them.

This is what I'm trying to achieve: ( for Source n I mean the category)

[![enter image description here][1]][1]

I used to use Yahoo!Pipes to make all these changes.

My attempt was to create a CustomListView for each url and then execute the AsyncTasks all at once but that is not working correctly - the feeds are not displayed in ascending order.

MainActivity

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
    private RSSFeed myRssFeed = null;
    String[] urlFeed = {"url1", "url2"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        for (int i = 0; i < urlFeed.length; i++) {
            News news = new News(i);
            news.execute();
        }
    }

    @Override
    public void onRefresh() {
        for (int i = 0; i < urlFeed.length; i++) {
            News news = new News(i);
            news.execute();
        }
    }

    private class News extends AsyncTask<Object, Void, Void> {
        protected int number;
        public News(int urlNumber) {
            number = urlNumber;
        }

        @Override
        protected Void doInBackground(Object... arg0) {

            String data = "";
            InputStream iStream;

            try{
                URL url = new URL(urlFeed[number]);

                // Creating an http connection to communicate with url
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

                // Connecting to url
                urlConnection.connect();

                // Reading data from url
                iStream = urlConnection.getInputStream();

                BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

                StringBuilder sbf  = new StringBuilder();

                String line;
                while( ( line = br.readLine())  != null){
                    sbf.append(line);
                }

                data = sbf.toString();

                br.close();

                SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
                SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
                XMLReader myXMLReader = mySAXParser.getXMLReader();
                RSSHandler myRSSHandler = new RSSHandler();
                myXMLReader.setContentHandler(myRSSHandler);
                InputSource myInputSource = new InputSource(url.openStream());
                myXMLReader.parse(myInputSource);

                myRssFeed = myRSSHandler.getFeed();

            } catch (ParserConfigurationException | IOException | SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            if (myRssFeed != null) {

                NestedListView list = (NestedListView)findViewById(android.R.id.list);
                list.setVisibility(View.VISIBLE);
                CustomList adapter = new CustomList(MainActivity.this, myRssFeed.getList());
                adapter.addAll();
                list.setAdapter(adapter);

            } else
                Toast.makeText(MainActivity.this, "Error",
                    Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
}

RSSFeed

public class RSSFeed {
    private String title = null;
    private String description = null;
    private String link = null;
    private String pubdate = null;
    private String image = null;
    private String enclosure = null;
    private String author = null;
    private List<RSSItem> itemList;

    RSSFeed(){
        itemList = new Vector<RSSItem>(0);
    }

    void addItem(RSSItem item){
        itemList.add(item);
    }
    RSSItem getItem(int location){
        return itemList.get(location);
    }
    List<RSSItem> getList(){
        return itemList;
    }

}

RSSItem

public class RSSItem {

    private String title = null;
    private String description = null;
    private String link = null;
    private String pubdate = null;
    private String image = null;
    private String enclosure = null;
    private String author = null;
}

CustomList

public class CustomList extends ArrayAdapter<RSSItem> {

    private static Activity context = null;
    private final List<RSSItem> web;

    public CustomList(Activity context, List<RSSItem> web) {
        super(context, R.layout.new_listview, web);
        CustomList.context = context;
        this.web = web;
    }

    @SuppressLint("SetTextI18n")
    @Override
    public View getView(final int position, View view, ViewGroup parent) {
        LayoutInflater inflater = context.getLayoutInflater();
        @SuppressLint({"ViewHolder", "InflateParams"}) final View rowView = inflater.inflate(R.layout.new_listview, null, true);
        ImageView imageView = (ImageView)rowView.findViewById(R.id.image);
            Picasso.with(context).load(web.get(position).getImage()).into(imageView);

        TextView textView = (TextView)rowView.findViewById(R.id.title);
        textView.setText(Html.fromHtml(web.get(position).getTitle()));

        TextView textView1 = (TextView)rowView.findViewById(R.id.description);
        textView1.setText(web.get(position).getDescription());

        TextView textView2 = (TextView)rowView.findViewById(R.id.pubdate);
        textView2.setText(pubdate);

        return rowView;

    }

}

RSSHandler

public class RSSHandler extends DefaultHandler {

    final int state_unknown = 0;
    final int state_title = 1;
    final int state_description = 2;
    final int state_link = 3;
    final int state_pubdate = 4;
    final int state_enclosure = 6;
    final int state_image = 5;
    final int state_author = 7;
    int currentState = state_unknown;
    String url;

    RSSFeed feed;
    RSSItem item;

    boolean itemFound = false;

    RSSHandler(){
    }

    RSSFeed getFeed(){
        return feed;
    }

    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        feed = new RSSFeed();
        item = new RSSItem();

    }

    @Override
    public void startElement(String uri, String localName, String qName,
                         Attributes attributes) throws SAXException {

        // TODO Auto-generated method stub

        if (localName.equalsIgnoreCase("item")){
            itemFound = true;
            item = new RSSItem();
            currentState = state_unknown;
        }
        else if (localName.equals("enclosure")) {
            url = attributes.getValue("url");
            currentState = state_image;
        }
        else if (localName.equalsIgnoreCase("title")){
            currentState = state_title;
        }
        else if (localName.equalsIgnoreCase("description")){
            currentState = state_description;
        }
        else if (localName.equalsIgnoreCase("link")){
            currentState = state_link;
        }
        else if (localName.equalsIgnoreCase("pubdate")){
            currentState = state_pubdate;
        }
        else if (localName.equalsIgnoreCase("author")){
            currentState = state_author;
        }
        else{
            currentState = state_unknown;
        }

    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // TODO Auto-generated method stub
        if (localName.equalsIgnoreCase("item")){
            feed.addItem(item);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
        throws SAXException {
        // TODO Auto-generated method stub

        String strCharacters = new String(ch,start,length);

        if (itemFound){
            // "item" tag found, it's item's parameter
            switch(currentState){
                case state_enclosure:
                    item.setEnclosure(strCharacters);
                    break;
                case state_title:
                    item.setTitle(strCharacters);
                    break;
                case state_image:
                    item.setImage(url);
                    break;
                case state_description:
                    item.setDescription(strCharacters);
                    break;
                case state_link:
                    item.setLink(strCharacters);
                    break;
                case state_pubdate:
                    item.setPubdate(strCharacters);
                    break;
                case state_author:
                    item.setAuthor(strCharacters);
                    break;
                default:
                    break;
            }
        }
        else{
            // not "item" tag found, it's feed's parameter
            switch(currentState){
                case state_enclosure:
                    feed.setEnclosure(strCharacters);
                    break;
                case state_title:
                    feed.setTitle(strCharacters);
                    break;
                case state_image:
                    feed.setImage(url);
                    break;
                case state_description:
                    feed.setDescription(strCharacters);
                    break;
                case state_link:
                    feed.setLink(strCharacters);
                    break;
                case state_pubdate:
                    feed.setPubdate(strCharacters);
                    break;
                case state_author:
                    feed.setAuthor(strCharacters);
                    break;
                default:
                    break;
            }
        }

        currentState = state_unknown;
    }
like image 975
Rick Avatar asked Oct 31 '22 09:10

Rick


1 Answers

The solution requires more than one change. The first thing you need to do is make each News task that finishes adds its data to the one big list. That list can then be sorted which requires a Comparator.

You also need a list of the names to show in the placeholder youve called Source n in your image and lastly, so that you can compare them, you need to parse the dates as actual dates.

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    private List<RSSItem> totalRssFeed = new ArrayList<>();
    String[] urlFeed = {"MyURL", "MyUrl2", "MyUrl3"};
    String[] names = {"Name", "Name2", "Name3"} 
    private CustomList adapter;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        ListView list = (ListView) findViewById(android.R.id.list);
        adapter = new CustomList(MainActivity.this);
        list.setAdapter( adapter );
    }

    @Override
    protected void onResume() {
        // do this here and you dont need to repeat it in refresh and create
        for (int i = 0; i < urlFeed.length; i++) {
            News news = new News(i);
            news.execute();
        }
    }

    public class CustomList extends ArrayAdapter<RSSItem> {

        ...

        public CustomList(Activity context) { //dont start with default data
            super(context, R.layout.new_listview, null);
        }

        ...

    }

    private class News extends AsyncTask<Object, Void, Void> {

        protected int number;

        public News(int urlNumber) {
            number = urlNumber;
        }

        @Override
        protected Void doInBackground(Object... arg0) {
            try {

                //no need to do the input stuff you were doing before here?
                URL url = new URL(urlFeed[number]);
                SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
                SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
                XMLReader myXMLReader = mySAXParser.getXMLReader();
                RSSHandler myRSSHandler = new RSSHandler(names[number]);
                myXMLReader.setContentHandler(myRSSHandler);
                InputSource myInputSource = new InputSource(url.openStream());
                myXMLReader.parse(myInputSource);
                totalRssFeed.addAll(myRSSHandler.getFeed());
                Collections.sort(totalRssFeed);

            } catch (ParserConfigurationException | IOException | SAXException e) { /* stuff */ }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            adapter.clear();
            adapter.addAll(totalRssFeed);
        }

    }

    public class RSSItem implements Comparable<RSSItem> {

        public String tag;
        public Date pubdate; //just public so i didnt need setters in this example

        public RSSItem(String defaultTagToUse) {
            //You should set the default to whatever you want displayed
            //when the tag for <category> is missing, and just update it normally otherwise
            tag = defaultTagToUse;
        }

        void setPubDate(Date date) {
            pubdate = date;
        }

        ...

        @Override
        public int compareTo(@NonNull RSSItem another) {
            int res;
            if (pubdate == null) {
                if (another.pubdate == null) {
                    res = 0;
                } else {
                    res = -1;
                }
            } else {
                if (another.pubdate == null || pubdate.getTime() > another.pubdate.getTime()) {
                    res = 1;
                } else {
                    res = -1;
                }
            }
            return res;
        }

    }

    public class RSSHandler extends DefaultHandler {

        ...
        List<RSSItem> feed;
        RSSItem item;
        String mName;

        public RssHandler(String name) {
            mName = name;
        } 

        List<RSSItem> getFeed() {
            return feed;
        }

        @Override
        public void startDocument() throws SAXException {
            feed = new ArrayList<>();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if (localName.equalsIgnoreCase("item")) {
                itemFound = true;
                item = new RSSItem( name ); 
                currentState = state_unknown;
            } else ...
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if (localName.equalsIgnoreCase("item")) {
                feed.add(item);
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            ...
            case state_pubdate:
                SimpleDateFormat formatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); //make sure you match the format from your XML
                item.setPubdate( formatter.parse(stringCharacters) );
            break;
            ...
        }
    }
}

All the ...'s jsut mean leave everything as it was in those places

like image 94
Nick Cardoso Avatar answered Nov 15 '22 05:11

Nick Cardoso