Home » Android » I check all the forum but not find a solution | “Open external links of my webview in browser and not in app” does not work

I check all the forum but not find a solution | “Open external links of my webview in browser and not in app” does not work

Posted by: admin November 1, 2017 Leave a comment

Questions:

thanks for read my question 🙂 I am not able to solve this problem after check all the forum. I am working on my first webview. Nothing special. It’s a webview with progress bar. My code in “shouldOverrideUrlLoading” method is not working. I want that all external links of my site open in browser and not in app, but it does not work. Can anyone please check my code?

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

private WebView wv;
private ProgressBar progressBar;
private FrameLayout frameLayout;
SwipeRefreshLayout swipe;

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

    frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
    progressBar = (ProgressBar) findViewById(R.id.progressBar);
    progressBar.setMax(100);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    swipe = (SwipeRefreshLayout) findViewById(R.id.swipe);
    swipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            String webUrl = wv.getUrl();
            wv.loadUrl(webUrl);
        }
    });
    LoadWeb();

}

public void LoadWeb(){

    wv = (WebView)findViewById(R.id.webView);
    WebSettings settings = wv.getSettings();
    settings.setJavaScriptEnabled(true);

    wv.loadUrl("example.com");
    swipe.setRefreshing(true);
    wv.setWebViewClient(new HelpClient());
    wv.setWebViewClient(new MyAppWebViewClient());

    wv.setWebChromeClient(new WebChromeClient(){
        public void onProgressChanged(WebView view, int progress){
            frameLayout.setVisibility(View.VISIBLE);
            progressBar.setProgress(progress);

            if (progress == 100){
                frameLayout.setVisibility(View.GONE);

            }
            super.onProgressChanged(view, progress);
        }
    });
    progressBar.setProgress(0);

    wv.setWebViewClient(new WebViewClient(){

        public void onPageFinished(WebView view, String url){
            swipe.setRefreshing(false);
        }
    });

}

private class HelpClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url){
        view.loadUrl(url);
        frameLayout.setVisibility(View.VISIBLE);
        return true;

    }
}

private class MyAppWebViewClient extends WebViewClient {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        if(Uri.parse(url).getHost().endsWith("example.com")) {
            return false;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
    }

}

@Override
public void onBackPressed() {
    if(wv.canGoBack()) {
        wv.goBack();
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement


    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_home) {
        wv.loadUrl("example.com");

    } else if (id == R.id.nav_facebook) {

        try {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("fb://page/idfbpage"));
            startActivity(intent);
        } catch (Exception e) {
            Intent intent =  new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/idfbpage"));
            startActivity(intent);
        }

    } else if (id == R.id.nav_instagram) {

        Uri uri = Uri.parse("http://instagram.com/_u/idinstapage");
        Intent likeIng = new Intent(Intent.ACTION_VIEW, uri);
        likeIng.setPackage("com.instagram.android");

        try {
            startActivity(likeIng);
        } catch (Exception e) {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://instagram.com/idinstapage")));
        }

    } else if (id == R.id.nav_star) {

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("market://details?id=idpackage"));
        startActivity(intent);

    } else if (id == R.id.nav_informazioni) {
        wv.loadUrl("example.com/info-app");

    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
 }

}
Answers:

In your method LoadWeb() there is an error because your WebView should have only one WebViewClient and only one WebChromeClient. So what happens is, if you use the method wv.setWebViewClient(new YourWebViewClient()); more than once what happens is that all other methods set before that are ignored because you can set it only once.

For your case:
You set the WebViewClient Three (3) times:

wv.setWebViewClient(new HelpClient());   //First time
wv.setWebViewClient(new MyAppWebViewClient());  //Second time

And the last time you set it down in your same method you set another like:

wv.setWebViewClient(new WebViewClient(){

    public void onPageFinished(WebView view, String url){
        swipe.setRefreshing(false);
    }
});

So what happens is that the two previous methods were ignored and the only method that was working was the last one (the third) only. That’s why I asked you to put the second method down to setWebClient((new MyAppWebViewClient()); so as to ignore the previous!

THE SOLUTION
Now you know we have to set only one WebViewClient for your webView we have to make only ONE Class that will be used to and do the job of all three other WebViewClient by overriding all the required methods. Make this class inside your activity but oustide your any method (just like how you have done when making in HelpClient() Class). Here is Our Class Please make sure you read the Comments in it!

private class NewWebViewClient extends WebViewClient {
       //Now we have only one class to do a job of all the other three!

    @Override
    public void onPageFinished(WebView view, String url) {
        /*I here do whatever you want to do when the page has finished loading! Do it here inside this method and it will work may be control the framelayout visibility For example lets setRefreshing false to our swipe()*/
        swipe.setRefreshing(false);
        //.....add more methods you want here when the page loading is finished
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        /*In this method we are going to tell the android system what kind of link we want and what kind of link we dont want for that what we want we will handle for the extra the browser should do so!*/
        if (Uri.parse(url).getHost().endsWith("example.com")) {
            //if the code gets here this is your link then right? Lets do whatever we want with our link and logic for example lets set framelayout visible or doing anything this link's host is example.com!
            frameLayout.setVisibility(View.VISIBLE);
            return false;
        } else {
            //Ooops This link is not yours lets just open browsers right 
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            view.getContext().startActivity(intent);
            return true;
        }

    }

}

After your class is beautiful then lets just set our WebViewClient only ONCE.

wv.setWebViewClient(new NewWebViewClient());

You can just ignore the WebChromeClient because you set it only once you are good. Comment below if you find any difficulties!

Questions:
Answers:

I hope removing the this line

wv.setWebViewClient(new MyAppWebViewClient());

will solve the problem for you.

Questions:
Answers:

You are using two instances of WebViewClient ,remove one ,

private class MyAppWebViewClient extends WebViewClient {

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    Log.d("TAG",url);
    if(Uri.parse(url).getHost().equals("example.com")) {
        return false;
    }
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    view.getContext().startActivity(intent);//add the brakpoint here
    Log.d("TAG","Starting activity");
    return true;
}

}

just use this