Home > Enterprise >  How to save RSS feed data into SQLite in Android?
How to save RSS feed data into SQLite in Android?

Time:01-31

I am able to parse RSS feeds successfully in android studio, but I would like to save the parsed data into database, so if I am offline, i will still be able to retrieve from the saved data.

here is my MainActivity

package com.jjurrius.simplerssvideo;

import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    ListView lvRss;
    ArrayList<String> titles;
    ArrayList<String> links;
    private DatabaseHandler db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvRss = (ListView) findViewById(R.id.lvRss);

        titles = new ArrayList<String>();
        links = new ArrayList<String>();
        db = new DatabaseHandler(this);

        try {
            db.open();
            NewsInformation item = new NewsInformation();
            item.completeTextLink = "Your Link of news";
            item.title            = "title of news";
            item.writerName       = "writer of news";
            item.dateWriten       = "1999";
            item.source           = "something";
            item.smallBody        = "news body";
            item.bigBody          = "news text";
            item.page             = "1";
            db.insertNewsInfo(item);
            db.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }


        lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                Uri uri = Uri.parse(links.get(position));
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                startActivity(intent);
            }
        });

        new ProcessInBackground().execute();
    }

    public InputStream getInputStream(URL url)
    {
        try
        {
            return url.openConnection().getInputStream();
        }
        catch (IOException e)
        {
            return null;
        }
    }

    public class ProcessInBackground extends AsyncTask<Integer, Void, Exception>
    {
        ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);

        Exception exception = null;
        @Override
        protected void onPreExecute() {
            progressDialog.setMessage("Fetching Latest News!");
            progressDialog.show();

        }

        @Override
        protected Exception doInBackground(Integer... integers) {
            try
            {

                // rss feed site here
                URL url = new URL("https://moxie.foxnews.com/feedburner/world.xml");
                // factory new instance
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                factory.setNamespaceAware(false);
                XmlPullParser xpp = factory.newPullParser();
                xpp.setInput(getInputStream(url),"UTF_8");

                boolean insideItem = false;

                int eventType = xpp.getEventType();

                while (eventType != XmlPullParser.END_DOCUMENT)
                {
                    if(eventType == XmlPullParser.START_TAG)
                    {
                        if(xpp.getName().equalsIgnoreCase("item"))
                        {
                            insideItem = true;
                        }
                        else if (xpp.getName().equalsIgnoreCase("title"))
                        {
                            if(insideItem)
                            {
                                titles.add(xpp.nextText());

                            }
                        }

                    }
                    else if(eventType == XmlPullParser.START_TAG && xpp.getName().equalsIgnoreCase("item"))
                    {
                        insideItem = false;
                    }

                    eventType = xpp.next();
                }
            }
            catch (MalformedURLException e)
            {
                exception = e;
            }
            catch (XmlPullParserException e)
            {
                exception = e;
            }
            catch (IOException e)
            {
                exception = e;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Exception s) {
            super.onPostExecute(s);

            ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,titles);

            lvRss.setAdapter(adapter);
            progressDialog.dismiss();

        }
    }
}

My NewsInformation.java

package com.jjurrius.simplerssvideo;

public class NewsInformation
{
    public String completeTextLink;
    public String title;
    public String writerName;
    public String dateWriten;
    public String source;
    public String smallBody;
    public String bigBody;
    public String page;
}

My DabaseHelper.java

package com.jjurrius.simplerssvideo;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DatabaseHelper extends SQLiteOpenHelper {

    private final String TAG = "DatabaseHelper";
    private static final String DATABASE_NAME = "db_for_news";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, 10);

        //fdd
        Log.i(TAG, "Object created.");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE news ( page TEXT ,"  
                " completeTextLink TEXT  ,title TEXT , writerName TEXT , dateWriten TEXT ,"  
                " source TEXT ,  smallBody TEXT , bigBody TEXT);");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(DatabaseHelper.class.getName(), "Upgrading database from version "
                  oldVersion   " to "   newVersion   ", which will destroy all old data");
        db.execSQL("Drop table if exists news" );
        onCreate(db);
    }
}

My DatabaseHandler.java

package com.jjurrius.simplerssvideo;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DatabaseHandler {

    private DatabaseHelper dbHelper;
    private SQLiteDatabase database;


    public DatabaseHandler(Context context) {
        dbHelper = new DatabaseHelper(context);
    }

    //methods for all table
    public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }

    public void close() {
        dbHelper.close();
    }

    public void clearTable(String tableName) {
        database.delete( tableName, null, null);
    }

    //news table method

    public void insertNewsInfo(NewsInformation newsInfo) {
        ContentValues cv = new ContentValues();
        cv.put("bigBody"          ,  newsInfo.bigBody );
        cv.put("completeTextLink" ,  newsInfo.completeTextLink );
        cv.put("dateWriten"       ,  newsInfo.dateWriten );
        cv.put("source"            ,  newsInfo.source );
        cv.put("smallBody"        ,  newsInfo.smallBody );
        cv.put("title"            ,  newsInfo.title );
        cv.put("writerName"       ,  newsInfo.writerName );
        cv.put("page"             ,  newsInfo.page );

        database.insert("news" , "writerName", cv);
    }


    public List<NewsInformation> getAllNewsForPage(String page) {
        List<NewsInformation> NewsInfoList = new ArrayList<NewsInformation>();

        Cursor cursor = database.rawQuery("select completeTextLink "  
                " , title , writerName , dateWriten , source , smallBody , bigBody"  
                " FROM news where page = ?", new String[]{page});


        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            NewsInformation newsInfo = new NewsInformation();

            newsInfo.completeTextLink = cursor.getString(0);
            newsInfo.title = cursor.getString(1);
            newsInfo.writerName = cursor.getString(2);
            newsInfo.dateWriten = cursor.getString(3);
            newsInfo.source = cursor.getString(4);
            newsInfo.smallBody = cursor.getString(5);
            newsInfo.bigBody = cursor.getString(6);
            newsInfo.page = page;

            NewsInfoList.add(newsInfo);
            cursor.moveToNext();
        }

        // Make sure to close the cursor
        cursor.close();

        return NewsInfoList;
    }

    public String getBigBody(String completeBodyLink) {
        Cursor cursor = database.rawQuery("select bigBody FROM news where completeTextLink = ?", new String[]{completeBodyLink});
        cursor.moveToFirst();
        String bigBody = cursor.getString(0);
        cursor.close();
        return bigBody;
    }
}

When I run the app, it shows me the rss feeds, but I can't save them. I dont know where the error is.

Here is my github repo: SimpleRssFeed

CodePudding user response:

Hello my friend; i have changed your code, for better understanding i used Document,Element,NodeList Objects for fetching Rss. inside doInBackground Method we fetch all required fields in rss and creating NewsInformation object, and finally we get list of NewsInformation and in onPostExecute method add them to DB and Listview Adapter, here is my changes in your code:

your data-object

    public class NewsInformation
{
    public String link;
    public String title;
    public String pubdate;
    public String category;

}

and your activity:

    import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.appcompat.app.AppCompatActivity;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

public class RssReader extends AppCompatActivity {

    ListView lvRss;
    ArrayList<String> titles;
    ArrayList<String> links;
    ArrayList<NewsInformation> news =new ArrayList<>();
    private DatabaseHandler db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.rss_reader);
        lvRss = (ListView) findViewById(R.id.lvRss);

        titles = new ArrayList<String>();
        links = new ArrayList<String>();
        db = new DatabaseHandler(this);


        lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                Uri uri = Uri.parse(links.get(position));
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                startActivity(intent);
            }
        });

        new ProcessInBackground().execute();
    }

    public InputStream getInputStream(URL url) {
        try {
            return url.openConnection().getInputStream();
        } catch (IOException e) {
            return null;
        }
    }

    public class ProcessInBackground extends AsyncTask<Integer, Void, Exception> {
        ProgressDialog progressDialog = new ProgressDialog(RssReader.this);

        Exception exception = null;

        @Override
        protected void onPreExecute() {
            progressDialog.setMessage("Fetching Latest News!");
            progressDialog.show();

        }

        @Override
        protected Exception doInBackground(Integer... integers) {
            try {
                // rss feed site here
                URL url = new URL("https://moxie.foxnews.com/feedburner/world.xml");

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();

                Document doc = db.parse(getInputStream(url));

                doc.getDocumentElement().normalize();
                NodeList nodeList = doc.getElementsByTagName("item");
                Log.e("node size:", String.valueOf(nodeList.getLength()));
                //// fetch every node item in RSS and create news_item list
                for (int i = 0; i < nodeList.getLength(); i  ) {
                    NewsInformation news_item = new NewsInformation();
                    Node node = nodeList.item(i);
                    Element parentItem = (Element) node;

                    NodeList links = parentItem.getElementsByTagName("link");
                    Element element_link = (Element) links.item(0);
                    NodeList element_link_childNodes = element_link.getChildNodes();
                    news_item.link = element_link_childNodes.item(0).getNodeValue();


                    NodeList titles = parentItem.getElementsByTagName("title");
                    Element element_title = (Element) titles.item(0);
                    NodeList element_title_childNodes = element_title.getChildNodes();
                    news_item.title = element_title_childNodes.item(0).getNodeValue();


                    NodeList pubDates = parentItem.getElementsByTagName("pubDate");
                    Element element_pubDate = (Element) pubDates.item(0);
                    NodeList element_pubDate_childNodes = element_pubDate.getChildNodes();
                    news_item.pubdate = element_pubDate_childNodes.item(0).getNodeValue();


                    NodeList categorys = parentItem.getElementsByTagName("pubDate");
                    Element element_category = (Element) categorys.item(0);
                    NodeList element_category_childNodes = element_category.getChildNodes();
                    news_item.category = element_category_childNodes.item(0).getNodeValue();

                    news.add(news_item);

                   //////////////////////////////////////////////////////////////////////////////////////////////

                }


            } catch (MalformedURLException e) {
                exception = e;
                Log.e("nerror1:", String.valueOf(e));
            } catch (IOException e) {
                exception = e;
                Log.e("nerror2:", String.valueOf(e));
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
                Log.e("nerror3:", String.valueOf(e));
            } catch (SAXException e) {
                e.printStackTrace();
                Log.e("nerror4:", String.valueOf(e));
            }
            return null;
        }

        @Override
        protected void onPostExecute(Exception s) {
            super.onPostExecute(s);
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(RssReader.this, android.R.layout.simple_list_item_1, titles);
            lvRss.setAdapter(adapter);

//////////// after fetching data insert to db///////////////////////////////////////////
                try {
                    db.open();
                    for (int i = 0; i < news.size();   i) {
                        db.insertNewsInfo(news.get(i));
                    }
                    db.close();

                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }

/////////////////////////////////////////////////////////////////////////////
            progressDialog.dismiss();

        }
    }
}

as an advise i recommend you:

  • use coroutines library instead of AsyncTask classes (read about coroutines)

  • for http/https request use retrofit library

  • use Room instead of dataBaseHandler

  •  Tags:  
  • Related