-2

I'm trying to implement a Newsreader app following Udemy "Complete Android N Developer Course".List view is used.

As per the instruction I have correctly followed but when executing the below main activity though it is required to update the list items with titles, this shows nothing in the list view. No errors even in the Android Monitor.

Any suggestion to find the issue, please.

Thank you!

public class MainActivity extends AppCompatActivity {

    ArrayList<String > titles = new ArrayList<>();
    ArrayList<String> content = new ArrayList<>();
    ArrayAdapter arrayAdapter;
    SQLiteDatabase articleDB ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.listView );
        arrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,titles);
        listView.setAdapter(arrayAdapter);
        articleDB = this.openOrCreateDatabase("articles",MODE_PRIVATE,null);
        articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, articleID INTEGER,title VARCHAR,content VARCHAR)");
        updateListView();
        DownloadTask task = new DownloadTask();
        try {
            task.execute("https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty");
        }catch(Exception e){
           e.printStackTrace();
        }
    }
    //update table
    public void updateListView(){
        Cursor c = articleDB.rawQuery("SELECT * FROM articles", null);
        int contentIndex = c.getColumnIndex("content");
        int titleIndex = c.getColumnIndex("title");
        if(c.moveToFirst()){
            titles.clear();
            content.clear();
            do{
                titles.add(c.getString(titleIndex));
                content.add(c.getString(contentIndex));
            }while (c.moveToNext());
            arrayAdapter.notifyDataSetChanged();
        }
    }
    public class DownloadTask extends AsyncTask<String, Void, String>{
        @Override
        protected String doInBackground(String... strings) {
            String result = "";
            URL url;
            HttpsURLConnection urlConnection = null;
            try {
                url = new URL (strings[0]);
                urlConnection = (HttpsURLConnection) url.openConnection();
                InputStream in = urlConnection.getInputStream();
                InputStreamReader reader = new InputStreamReader(in);
                int data = reader.read();
                while (data != -1){
                    char current = (char) data;
                    result += current;
                    data = reader.read();
                }
                //Log.i("URLContent",result);

                JSONArray jsonArray = new JSONArray(result);
                int numberOfItems = 20;
                if(jsonArray.length() <20){
                    numberOfItems = jsonArray.length();
                }
                //to clear the table before add data
                articleDB.execSQL("DELETE FROM articles"); //will clear everything and add a new data
                for (int i=0;i<numberOfItems;i++ ){
                    //Log.i("JSONItem",jsonArray.getString(i));
                    String articleId = jsonArray.getString(i);
                    url = new URL("https://hacker-news.firebaseio.com/v0/item/"+articleId+".json?print=pretty");
                    urlConnection = (HttpsURLConnection) url.openConnection();
                    in = urlConnection.getInputStream();
                    reader = new InputStreamReader(in);
                    data = reader.read();
                    String articleInfo = "";
                    while (data!= -1){
                        char current = (char) data;
                        articleInfo += current;
                        data = reader.read();
                    }
                    //Log.i("ArticleInfo",articleInfo);
                    //separate title and URL
                    JSONObject jsonObject = new JSONObject(articleInfo);
                    if (!jsonObject.isNull("title") && !jsonObject.isNull("url")){
                        String articleTitle = jsonObject.getString("title");
                        String articleURL = jsonObject.getString("url");
                        //Log.i("info",articleTitle + articleURL);
                        url = new URL(articleURL);
                        urlConnection = (HttpsURLConnection) url.openConnection();
                        in = urlConnection.getInputStream();
                        reader = new InputStreamReader(in);
                        data = reader.read();
                        String articleContent = "";
                        while (data!= -1){
                            char current = (char) data;
                            articleContent += current;
                            data = reader.read();
                        }
                        //Log.i("articleContent",articleContent);

                        String sql = "INSERT INTO articles(articleID,title,content) VALUES(? , ? , ?)";
                        SQLiteStatement statement = articleDB.compileStatement(sql);
                        statement.bindString(1,articleId);
                        statement.bindString(2,articleTitle);
                        statement.bindString(3,articleContent);
                        statement.execute();
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            //run when the download task is completed
            updateListView();
        }
    }
}
Sachz
  • 391
  • 5
  • 21
  • Try to use Log to test out connection, then your data to make sure its working first. – Saeed Joul Jul 30 '19 at 12:43
  • The logic here is FIRST make sure that you received correct data. SECOND make sure that data is compatible with the model and you can parse it. and THIRD that it is correctly inflate in the list. So log all these steps. BUT two notes. It is bad practice to make two list of strings it is better to make one object NEWS with for example String title and String description in it. Second is logic of getting JSON is bad. It can be much much shorter with retrofit. If you need help refactor let me know – Bo Z Jul 30 '19 at 12:48
  • If that course learn this way of development - throw it in the garbage. Try retrofit + recycler + regular model class = cleaner / faster – Bo Z Jul 30 '19 at 13:52
  • @BorisRuzanov thanks for the suggestions. I'm new to this I will try. I'm sorry I didn't get the information about retrofit :( perhaps I should google it. – Sachz Jul 30 '19 at 16:19

2 Answers2

0

I don't believe that you issues are SQLite based, but rather that the issues are with the retrieval of the data.

Issues could be :-

  1. That you do not have the respective permissions. So you need to check that your manifest has the permissions and that you have requested the run time permissions. See Request App Permissions

    • The testing below gets around the runtime permissions by using a pre API 24 device (emulator).
  2. Not using the appropriate connection type when retrieving, that is switch to an HTTP connection for HTTP url's. See the code below for a fix (may be better alternatives).

Test 1

For example, modifying your code (commenting out the code from ) to skip the data retrieval and adding the insertion of data for testing displays the inserted data.

e.g. :-

    protected String doInBackground(String... strings) {
        String result = "";
        URL url;
        HttpsURLConnection urlConnection = null;
        HttpURLConnection xurlConnection = null; //ADDED for stage 2 testing

        /* <<<<<<<<<<< COMMENT OUT DATA RETRIEVAL >>>>>>>>>>
        try {
            url = new URL (strings[0]);
            urlConnection = (HttpsURLConnection) url.openConnection();
            InputStream in = urlConnection.getInputStream();
            InputStreamReader reader = new InputStreamReader(in);
            int data = reader.read();
            while (data != -1){
                char current = (char) data;
                result += current;
                data = reader.read();
            }
            //Log.i("URLContent",result);

            JSONArray jsonArray = new JSONArray(result);
            int numberOfItems = 20;
            if(jsonArray.length() <20){
                numberOfItems = jsonArray.length();
            }
            //to clear the table before add data
            articleDB.execSQL("DELETE FROM articles"); //will clear everything and add a new data
            for (int i=0;i<numberOfItems;i++ ){
                //Log.i("JSONItem",jsonArray.getString(i));
                String articleId = jsonArray.getString(i);
                url = new URL("https://hacker-news.firebaseio.com/v0/item/"+articleId+".json?print=pretty");
                urlConnection = (HttpsURLConnection) url.openConnection();
                in = urlConnection.getInputStream();
                reader = new InputStreamReader(in);
                data = reader.read();
                String articleInfo = "";
                while (data!= -1){
                    char current = (char) data;
                    articleInfo += current;
                    data = reader.read();
                }
                //Log.i("ArticleInfo",articleInfo);
                //separate title and URL
                JSONObject jsonObject = new JSONObject(articleInfo);
                if (!jsonObject.isNull("title") && !jsonObject.isNull("url")){
                    String articleTitle = jsonObject.getString("title");
                    String articleURL = jsonObject.getString("url");
                    //Log.i("info",articleTitle + articleURL);
                    url = new URL(articleURL);
                    xurlConnection =  (HttpURLConnection) url.openConnection();
                    in = xurlConnection.getInputStream();
                    reader = new InputStreamReader(in);
                    data = reader.read();
                    String articleContent = "";
                    while (data!= -1){
                        char current = (char) data;
                        articleContent += current;
                        data = reader.read();
                    }
                    //Log.i("articleContent",articleContent);

                    String sql = "INSERT INTO articles(articleID,title,content) VALUES(? , ? , ?)";
                    SQLiteStatement statement = articleDB.compileStatement(sql);
                    statement.bindString(1,articleId);
                    statement.bindString(2,articleTitle);
                    statement.bindString(3,articleContent);
                    statement.execute();
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        <<<<<<<<<< END OF COMMENTED OUT CODE >>>>>>>>>> */
        ContentValues cv = new ContentValues();
        cv.put("articleID",1);
        cv.put("title","Title");
        cv.put("content","Some content");
        articleDB.insert("articles",null,cv);
        return null;
    }

Results in :-

enter image description here

  • This as is expected i.e. just the title is shown

Test 2

Removing the commented out code, initially results in a Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)

Test 3

Using a pre API 24 device (for the convenience of not having to request runtime permission) and changing the manifest to include <uses-permission android:name="android.permission.INTERNET"></uses-permission>

results in

 Caused by: java.lang.ClassCastException: com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection
    at aso.aso57271930listview.MainActivity$DownloadTask.doInBackground(MainActivity.java:117)
    at aso.aso57271930listview.MainActivity$DownloadTask.doInBackground(MainActivity.java:67)

Line 117 being urlConnection = (HttpsURLConnection) url.openConnection();

Test 4

Adding a breakpoint at line 117 and running in debug mode results in :-

enter image description here

  • the url is not https but http

Test 5

Adding line as per :-

protected String doInBackground(String... strings) {
        String result = "";
        URL url;
        HttpsURLConnection urlConnection = null;
        HttpURLConnection xurlConnection = null; //<<<<<<<<<< ADDED for stage 2 testing

And then changing as to use :-

                if (!jsonObject.isNull("title") && !jsonObject.isNull("url")){
                    String articleTitle = jsonObject.getString("title");
                    String articleURL = jsonObject.getString("url");
                    //Log.i("info",articleTitle + articleURL);
                    url = new URL(articleURL);
                    //urlConnection =  (HttpsURLConnection) url.openConnection(); //<<<<<<<<<< commented out
                    xurlConnection = (HttpURLConnection) url.openConnection(); //<<<<<<<<<< added to replace commented out line. 
                    in = urlConnection.getInputStream();
                    reader = new InputStreamReader(in);
                    data = reader.read();
                    String articleContent = "";
                    while (data!= -1){
                        char current = (char) data;
                        articleContent += current;
                        data = reader.read();
                    }
                    //Log.i("articleContent",articleContent);

                    String sql = "INSERT INTO articles(articleID,title,content) VALUES(? , ? , ?)";
                    SQLiteStatement statement = articleDB.compileStatement(sql);
                    statement.bindString(1,articleId);
                    statement.bindString(2,articleTitle);
                    statement.bindString(3,articleContent);
                    statement.execute();
                }

Results in :-

enter image description here

MikeT
  • 51,415
  • 16
  • 49
  • 68
-1

Your table is not getting created in db, change

articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, articleID INTEGER,title VARCHAR,content VARCHAR)");

to

articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, articleID INTEGER,title TEXT,content TEXT)");
  • Thank you, I tried as per the suggestions but it the output was same no titles in the list view. In Run console, it indicates as "Launching app" for a long time no any other output, no errors even. – Sachz Jul 30 '19 at 16:07