Is it possible to include both a back button and download listener in a Webview Fragment

Developing a simple webview app using Webview fragment has been successful. However, two issues have been encountered. Firstly, upon clicking the back button, the app closes down. Secondly, when clicking on an HTML page link, the default browser does not open and displays an error stating that the webpage cannot be accessed. The objective is to have all tabs opened in the same webview while ensuring that the back button and download links function correctly. Below is the code:

MyWebViewFragment.java

package com.example.com;

import android.app.Fragment;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MyWebViewFragment extends Fragment {

    ProgressDialog mProgress;
    WebView webview;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.web_fragment, container,
                false);

        Bundle bundle = getArguments();
        String url = bundle.getString("url");
        webview = (WebView) rootView.findViewById(R.id.webview1);

        WebSettings settings = webview.getSettings();
        settings.setJavaScriptEnabled(true);

        mProgress = ProgressDialog.show(getActivity(), "Loading",
                "Please wait for a moment...");

        webview.loadUrl(url);

        webview.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                if (mProgress.isShowing()) {
                    mProgress.dismiss();
                }
            }
        });

        return rootView;
    }

}

MainActivity.java

package com.example.com;

import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget ListView;

public class MainActivity extends Activity {
    String[] menutitles;
    TypedArray menuIcons;
    String[] pageUrl;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    private List<RowItem> rowItems;
    private CustomAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTitle = mDrawerTitle = getTitle();
        menutitles = getResources().getStringArray(R.array.titles);
        menuIcons = getResources().obtainTypedArray(R.array.icons);
        pageUrl = getResources().getStringArray(R.array.pageurl);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.slider_list);
        rowItems = new ArrayList<RowItem>();

        for (int i = 0; i < menutitles.length; i++) {
            RowItem items = new RowItem(menutitles[i], menuIcons.getResourceId(
                    i, -1), pageUrl[i]);
            rowItems.add(items);
        }

        menuIcons.recycle();

        adapter = new CustomAdapter(getApplicationContext(), rowItems);
        mDrawerList.setAdapter(adapter);
        mDrawerList.setOnItemClickListener(new SlideitemListener());

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                R.drawable.ic_drawer, R.string.app_name,
                R.string.app_name) {

            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu();
            }
        };

        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if (savedInstanceState == null) {
            updateDisplay(0);
        }
    }

    class SlideitemListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            updateDisplay(position);
        }
    }

    private void updateDisplay(int position) {
        String url = rowItems.get(position).getPageUrl();
        Fragment fragment = new MyWebViewFragment();

        Bundle bundle = new Bundle();
        bundle.putString("url", url);
        fragment.setArguments(bundle);
        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.frame_container, fragment).commit();
        setTitle(menutitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);

    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        switch (item.getItemId()) {
           case R.id.action_settings:
                return true;

          default:
             return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

}

Answer №1

If you want to display URLs in a webview, you can use the following code:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = (WebView) findViewById(R.id.webView);
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setPluginState(WebSettings.PluginState.OFF);
        webSettings.setSupportMultipleWindows(true);
        webSettings.setBuiltInZoomControls(true);
        webSettings.setAppCacheMaxSize(1);
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        webSettings.setAppCacheEnabled(false);

        // Additional settings for the webview
        webView.setWebChromeClient(new WebChromeClient());
        webView.clearCache(true);
        webView.setBackgroundColor(0);
        
        // WebViewClient methods
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                Log.e("", "shouldOverrideUrlLoading load url" + url);
                return false;
            }

            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
              // Error handling logic
            }

            public void onPageStarted(WebView view, String url, Bitmap favicon) {
              // Logic when page starts loading
            }

            public void onPageFinished(WebView view, String url) {
              // Logic after page finishes loading
            }
        });

        // Load the specified web link
        String web_link = "https://twitter.com";
        webView.loadUrl(web_link);
    }

    public void displayProgress(String title, String message) {
        if (progressDialog != null)
            progressDialog.dismiss();
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setMessage(message);
        progressDialog.setIndeterminate(false);
        progressDialog.setCancelable(true);

        try {
            progressDialog.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

To enable navigating back in the web view, override this method in your activity:

public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (web_link != null && !webView.getUrl().equals(web_link))
                webView.goBack();
            else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.to_exit)
                        .setCancelable(false)
                        .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                MainActivity.this.finish();
                            }
                        })
                        .setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        });
                AlertDialog alert = builder.create();
                alert.show();
            }
        }
        return super.onKeyDown(keyCode, event);
    }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Showing undefined or null values in React and JavaScript

My goal is to format undefined or null values by italicizing them. If the value is an empty string, it should be displayed as is. If it has a value, that value should also be displayed as is. However, I am encountering an issue where null or undefined val ...

Remove elements from an array in Typescript if they are not present in a nested array

I am struggling with filtering values from a single-dimensional array based on id matches in an array of objects. array1 = [1, 3, 15, 16, 18]; array2 = [ { id: 1, dinner : pizza }, { id: 15, dinner : sushi }, { id: 18, dinner : hummu ...

What is the process for implementing optional chaining on a JSON object?

I'm currently facing an issue where I need to compare a value within a JSON object with a variable. if (resp.userdetails.name == username) { // do something } The challenge arises when not all resp objects contain the userdetails property, resulting ...

The jQuery AJAX autocomplete result box is either too cramped or displaying numbers

I'm having some trouble setting up jQuery UI autocomplete with ajax in my project using CI 3.1.5. When I try to implement it, I either get a small result box or just the number of results. Here is my AJAX code snippet: $(".addClient").each(funct ...

Javascript only select values from the initial row of the table

I have a database that I am using to populate a table with results. To interact with these results, I utilize JavaScript in addition to PHP for retrieving values from the database and displaying them in the table. <table id="datatable" class="table tab ...

Is it possible for my commitment to consistently provide identical values, even when the data varies each time it is invoked?

Initially, the getCart method is invoked in b-navbar.component.ts: export class BNavbarComponent implements OnInit{ appUser: any; cart$ : Observable<ShoppingCart | null>; constructor(private auth : AuthService, private shoppingCartService : S ...

Leveraging window.hash and the power of WordPress htaccess

I have a Wordpress website where I am using Ajax to display posts in a specific section. I am currently having Javascript add the hash tag like this: window.location.hash = id; Everything is working as expected. For instance, it changes the URL to www.my ...

Is it possible to modify the parameters of a function by utilizing a MethodDecorator without affecting the "this" value?

Consider a scenario where you need to dynamically modify method arguments using a decorator at runtime. To illustrate this concept, let's simplify it with an example: setting all arguments to "Hello World": export const SillyArguments = (): MethodDec ...

Callback function triggered upon the creation of a DOM node

I am in search of a way to have a specific callback function run each time a div that matches a particular selector is added to the DOM. I have explored the DOM events documentation and the event closest to what I need seems to be "load", however, it does ...

How to safely add multiple objects to an array in TypeScript & React without replacing existing objects - Creating a Favorites list

I'm in the final stages of developing a weather application using TypeScipt and React. The last feature I need to implement is the ability for users to add queried locations to a favorites list, accessed through the "favorites" page. By clicking on a ...

What is the best way to specify the CSS :hover state within a jQuery selector?

I am trying to change the background color of a div element when hovered using jQuery, but for some reason the following code is not working as expected: $(".myclass:hover div").css("background-color","red"); Can someone provide guidance on how to achiev ...

Can we switch between using Vue components in .vue formats and commonJS formats seamlessly?

Here is the commonJS format: Vue.Component('custom-component',{ template : '<p>Some template</p>', data : {} methods : {} }); And here is the .vue format: <template> <p>Some template&l ...

What is the best way to remove a property from an object in React if the key's value is set to false?

I'm currently working on a form component and I've encountered an issue. Whenever I submit the form, it returns an object with various fields such as email, fieldName1, fieldName2, first_name, last_name, and organization. Some of these fields are ...

Press one button to activate another button

I am looking to activate a button's class by clicking on another button. The button I have is: <button class="clear-cart banner-btn">clear cart</button> This button is used for clearing a cart. On the order confirmation page, I click on ...

Angular 2 - synchronizing timer for all users

I have developed a timer that needs to function consistently for all users at the same time. To achieve this, I stored the start_time (timestamp when the timer begins) in my database and implemented the following code snippet to calculate the remaining ti ...

Angular8: Adjusting Activity Status After Leaving Page

When performing activities like upload, download, delete, and edit, I display statuses such as 'upload started' or 'upload completed'. This works perfectly when staying on the same page. However, there are instances where a user may nav ...

Issue when utilizing Renderscript api11+ along with support v8

I'm currently working on implementing a Blur effect using RenderScript from support v8, but I'm facing issues compiling the program. Here is the error message I am receiving: [2015-01-08 15:04:09 - Dex Loader] Unable to execute dex: Multiple de ...

Scanner (IE5) impact on page load speeds

I have developed an MVC project which is designed as a single-page application (SPA) utilizing knockoutjs and sammy frameworks. The following script is placed in the head section of the page: <script> var startTime = (new Date()).getTime(); </ ...

Adjust the alignment of an expansion panel header to the right using Vuetify

Incorporating the Vuetify expansion panel, I am aiming to align a specific portion of the content within the <div slote="head"></div> to the right, resulting in this desired layout: https://i.sstatic.net/tbOL8.jpg https://i.sstatic.net/22NTS. ...

Implementing the IF statement in jQuery

I've been trying to implement an overflow check when hovering over a div. The issue arises because I'm using jQuery for the hover function and then simple JavaScript for the overflow check in the next step. It seems that directly using an if-then ...