Search code examples
androidandroid-webviewback-button

How can I create a back button in a webview?


The app consists of two activities: first - a listview with links to HTML files from assets, second - a webview with this HTML file.

So there are some links in this HTML file (in the following I call it the first HTML file) leading to other HTML files from assets. After I followed one of this links I want to go back to the first HTML file. But this method shows me a white screen instead of the file's content.

PS: I reference the second asset file from first one by an HTML link. For example (code of link in the first HTML file):

<a href="file:///android_asset/second.html">Second file</a>

Here is the WebViewActivity code:

public class WebViewActivity extends Activity implements OnClickListener {
    WebView wWebView;

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                if (wWebView.canGoBack() == true) {
                    wWebView.goBack();
                } else {
                    finish();
                }
                return true;
            }

        }
        return super.onKeyDown(keyCode, event);
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Bundle bundle = getIntent().getExtras();

        String htmlFileName = "m" + bundle.getString("defStrID") + ".html";
        Context context = getBaseContext();

        try {
            String text = readAssetTextFile(context, htmlFileName);

            wWebView = (WebView) findViewById(R.id.webview);
            String summary = "<html><body>" + text + "</body></html>";
            wWebView.getSettings().setJavaScriptEnabled(true);
            wWebView.loadDataWithBaseURL("x-data://base", summary, "text/html",
                    "utf-8", null);
        } catch (IOException e) {
            Log.e("TAG", "Exception thrown", e);
        }
    }

    public static String readAssetTextFile(Context ctx, String fileName)
            throws IOException
    {
        InputStream inputStream = ctx.getAssets().open(fileName);

        InputStreamReader inputreader = new InputStreamReader(inputStream);
        BufferedReader buffreader = new BufferedReader(inputreader);
        String line;
        StringBuilder text = new StringBuilder();

        try {
            while ((line = buffreader.readLine()) != null) {
                text.append(line);
                text.append('\n');
            }
        } catch (IOException e) {
            Log.e("TAG", "Exception thrown", e);
        }
        return text.toString();
    }
}

Solution

  • Your problem is that the wWebView class member variable is not initialized so it is null. See this part of your code:

    WebView wWebView = (WebView) findViewById(R.id.webview);
    

    Perfect, you are initializing, but not what you think you are: you declare a local variable for the method and initialize it. However you shadow the class member wWebView, because of the local variable with the same name. Thus you do not initialize the class member, it is null and you get your NPE. Change the above line to (note the absence of the type):

    wWebView = (WebView) findViewById(R.id.webview);
    

    EDIT I was never able to make your way of navigating between the pages work. However I did certain changes to your onCreate method and now everything seems fine on my device:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
        TextView title = (TextView) findViewById(R.id.app_name);
        title.setText(getString(R.string.app_name));
    
        Button backButton = (Button) findViewById(R.id.button_back);
        backButton.setOnClickListener(this);
    
        Button infoButton = (Button) findViewById(R.id.button_info);
        infoButton.setOnClickListener(this);
    
        Bundle bundle = getIntent().getExtras();
    
        String htmlFileName = "m" + bundle.getString("defStrID") + ".html";
        String LINK_TO_ASSETS = "file:///android_asset/";
        wWebView = (WebView) findViewById(R.id.webview);
        wWebView.getSettings().setJavaScriptEnabled(true);
        wWebView.loadURL(LINK_TO_ASSETS + htmlFileName);
    }
    

    Now you need to change also the contents of the HTML files you load. First of all add the <html><body> at the beginning of each file in the assets and </body></html> at the end. Second now you will need to change your links. For example the link you have included in your question:

    <a href="second.html">Second file</a>
    

    As you see, these become now relative links. All these changes might make your readAssetTextFile useless, but I believe this is easier-to-understand code.