0

I am trying to get Information from a website and display it in an Android app. The second answer to the question "What is the fastest way to scrape HTML webpage in Android?" suggested to use BufferedReader. In the answer, the person uses the URL class. I tried to implement the answer like this:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import java.net.URL;

public class MainActivity extends AppCompatActivity {
    TextView display = (TextView) findViewById(R.id.textDisplay);

    @Override
    protected void onCreate(Bundle savedInstanceState) throws Exception {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        URL url = new URL("http://stackoverflow.com/questions/2971155");
        BufferedReader reader = null;
        StringBuilder builder = new StringBuilder();
        try {
            reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
            for (String line; (line = reader.readLine()) != null; ) {
                builder.append(line.trim());
            }
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException logOrIgnore) {
                    logOrIgnore.printStackTrace();
                }
            }
        }
        String start = "<div class=\"post-text\"><p>";
        String end = "</p>";
        String part = builder.substring(builder.indexOf(start) + start.length());
        String question = part.substring(0, part.indexOf(end));
        TextView display = (TextView) findViewById(R.id.textDisplay);
        display.setText(question);

    }


}

I got this error:

'onCreate(Bundle)' in 'com.example.myproject.MainActivity' clashes with 
'onCreate(Bundle)' in 'android.appcompat.app.AppCompatActivity';
 overridden method does not throw 'java.lang.Exception'

What would you suggest to handle this, is this a smart way of getting data from a website? Any help is much appreciated

Twisha Kotecha
  • 1,082
  • 1
  • 4
  • 18
MamoRatzo
  • 11
  • 4
  • Welcome to StackOverflow! Remove `throws Exception`, add `catch` to try block, you cannot modify method declaration when overriding. Also, you will get exception, because you are trying to execute network call on main thread. Use OkHttp library. And yeah, don't try to parse html manually (SO has json API, afaik) – Dmytro Rostopira Mar 04 '20 at 12:07

3 Answers3

0

First off - onCreate() should be public, not protected. Secondly, the signature of onCreate() does not throw an exception, so you can't add it when overriding. If you do want to throw, then the best you can do is remove the throws from the method signature, catch it, wrap it in a RuntimeException and rethrow it :

try {
  // .. your code
} catch(Exception e){
    throw new RuntimeException(e);
}finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException logOrIgnore) {
                    logOrIgnore.printStackTrace();
                }
            }
        }
Neeraj
  • 2,376
  • 2
  • 24
  • 41
0

Modify the code like this

    public class MainActivity extends AppCompatActivity {
        TextView display = (TextView) findViewById(R.id.textDisplay);

        @Override
        protected void onCreate(Bundle savedInstanceState) throws Exception {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

try{
            URL url = new URL("http://stackoverflow.com/questions/2971155");
            BufferedReader reader = null;
            StringBuilder builder = new StringBuilder();
            try {
                reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
                for (String line; (line = reader.readLine()) != null; ) {
                    builder.append(line.trim());
                }
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException logOrIgnore) {
                        logOrIgnore.printStackTrace();
                    }
                }
            }
            String start = "<div class=\"post-text\"><p>";
            String end = "</p>";
            String part = builder.substring(builder.indexOf(start) + start.length());
            String question = part.substring(0, part.indexOf(end));
            TextView display = (TextView) findViewById(R.id.textDisplay);
            display.setText(question);
}catch(Exception ex){
Log.e("EEXCCEption","ex.localizedMessage.toString()")

}

        }


    }

and in Logger file you can get the actual cause of exception.

Pawan Soni
  • 860
  • 8
  • 19
0

onCreate() method is part of Activity lifecycle, you are just overriding it (note @Override), not writing own, thus you can't change attributes, returning type or add/remove throws declarations

remove throws Exception from protected void onCreate(Bundle savedInstanceState) throws Exception { - this is causing your exception

and use try{}catch{}, e.g.

try {
    reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
    for (String line; (line = reader.readLine()) != null; ) {
        builder.append(line.trim());
    }
} catch(Exception e){
    e.printStackTrace();
    //TODO handle exception by own, don't throw outside onCreate, it will break lifecycle
} finally {
    ...

@Neeraj thats not true, in fact this is one and only thing you may change - class accessibility (public, protected etc.) - but only for "more-accessible" version, so protected to public, but not e.g. public to private. btw. in fact super version of this method is protected, @MamoRatzo didn't changed it, that's fine

snachmsm
  • 17,866
  • 3
  • 32
  • 74