12

I am loading a webpage in WebView. There is a link in the webpage, which on desktop will download the file, but in the app the link should display a Toast saying the link is disabled for the app.

I am not sure how to get the value from href of the anchor tag, when the link is clicked.

<a class="btn btn-primary" download="http://xx.xxx.com/wp-content/uploads/2015/11/abc-27-15.mp3" href="http://xx.xxx.com/wp-content/uploads/2015/11/abc-27-15.mp3">
<i class="fa fa-download"></i> Download Audio</a>

Can someone share an idea or any sample code on how to do this.

EDIT:1

Here is what I am doing currently:

private static final String URL = "http://xx.xxx.com/wp-content/uploads/";

webView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (event.getAction() == MotionEvent.ACTION_DOWN) {

                    WebView.HitTestResult hr = ((WebView) v).getHitTestResult();
                    String extra = hr.getExtra();

                    if (extra != null && extra.startsWith(URL) && extra.endsWith(".mp3")) {
                        Log.d("WebviewActivity", "Extra: " + extra);
                        Log.d("WebviewActivity", "Contains URL");

                        return true;
                    } 
                }

                return false;
            }
        });

The problem with this approach is: When i click on the link, i get the url in extra. It works fine till here. But, from next time, no matter where i click on the webview, the same extra is being returned. So even if i click on an image after i click on the url, i get the same url in the extra. Not sure if i doing anything wrong. Or is this the correct approach.

Please let me know if you need any details.

EDIT:2

private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // Get link-URL.
            String url = (String) msg.getData().get("url");

            // Do something with it.
            if (url != null) {
                Log.d(TAG, "URL: "+url);
            }
        }
    };



        webView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (event.getAction() == MotionEvent.ACTION_DOWN) {

                    WebView.HitTestResult hr = ((WebView) v).getHitTestResult();


                    if (hr.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {

                        Message msg = mHandler.obtainMessage();
                        webView.requestFocusNodeHref(msg);
                    }


                }

                return false;
            }
        });



        webView.loadUrl(mUrl);

    }

Now, i get the URL that is clicked in the last action_down event. How to get the current URL?

EDIT 3 (Attempt with webviewclient:

 private class MyWebViewClient extends WebViewClient {

        private static final String URL = "xx.xxx.com/wp-content/uploads/";

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);

            if (!isFinishing())
                mProgressDialog.show();
        }

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

        @Override
        public void onReceivedError(WebView view, int errorCode,
                                    String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);

            Toast.makeText(WebviewActivity.this,
                    "Please check your internet " + "connection and try again",
                    Toast.LENGTH_SHORT).show();
        }


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

            Log.d("xxx", "Url: " + url);

            if(url.contains(URL)) {
                Log.d("xxx", "Url Contains: " + URL);
                return true;
            }

            return false;
        }

    }


mMyWebViewClient = new MyWebViewClient();
        webView.setWebViewClient(mMyWebViewClient);

Output in logcat when the link is clicked:

03-01 15:38:19.402 19626-19626/com.xx.xxx D/cr_Ime: [ImeAdapter.java:553] focusedNodeChanged: isEditable [false]
03-01 15:38:19.428 19626-19626/com.xx.xxx D/cr_Ime: [ImeAdapter.java:253] updateKeyboardVisibility: type [0->0], flags [0], show [true], 
03-01 15:38:19.428 19626-19626/com.xx.xxx D/cr_Ime: [ImeAdapter.java:326] hideKeyboard
03-01 15:38:19.429 19626-19626/com.xx.xxx D/cr_Ime: [InputMethodManagerWrapper.java:56] isActive: true
03-01 15:38:19.429 19626-19626/com.xx.xxx D/cr_Ime: [InputMethodManagerWrapper.java:65] hideSoftInputFromWindow
Vamsi Challa
  • 11,038
  • 31
  • 99
  • 149

2 Answers2

7

Because you are using a WebView and the link is not Java script this is very easy to achieve with a WebViewClient which you can use to monitor your WebView

myWebView.setWebViewClient( new WebViewClient() {

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // check something unique to the urls you want to block
        if (url.contains("xx.xxx.com")) {
            Toast.make... //trigger the toast
            return true; //with return true, the webview wont try rendering the url
        }
        return false; //let other links work normally
    }

} );

It's possible that because your URL ends in .mp3 the file is being treated as a resource. You should also override the shouldInterceptRequest method of the WebViewClient to check this.

@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { 
    String url = request.getUrl().toString();
    Log.d("XXX", "Url from API21 shouldInterceptRequest : " + url);
    if (url.contains(URL)) { 
        return new WebResourceResponse("text/html", "UTF-8", "<html><body>No downloading from app</body></html>");
    } else {
        return null;
    }
}

public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
    Log.d("XXX", "Url from shouldInterceptRequest : " + url);
    if (url.contains(URL)) { 
        return new WebResourceResponse("text/html", "UTF-8", "<html><body>No downloading from app</body></html>");
    } else {
        return null;
    }
}
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • Sorry for the late reply. I tried this approach at the very beginning. But, when i click on the link, shouldOverrideUrlLoading is not getting called. The only time i am getting the url is when i use onTouchListener on the WebView as i mentioned in the Question's code sample – Vamsi Challa Mar 01 '16 at 09:43
  • If the webview client is set on the webview correctly, get URLs always cause the method to be called. If it is a form post it's not the case but you said an anchor link. Did you use this at the same time as the touch listener? Because of course that won't work when you are cancelling the event – Nick Cardoso Mar 01 '16 at 09:49
  • I updated the question with WebViewClient. Please have a look. I am not using both at the same time. First i tried with WebViewClient, but, i couldn't get the url from shouldOverrideUrlLoading. So, i was trying with onTouchListener. – Vamsi Challa Mar 01 '16 at 09:55
  • private static final String URL = "http://xx.xxx.com/wp-content/uploads/"; I am Logging it in shouldOverrideUrlLoading. @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.d("xxx", "Url: " + url); if(url.contains(URL)) { Log.d("xxx", "Url Contains: " + URL); return true; } return false; } – Vamsi Challa Mar 01 '16 at 10:00
  • The problem is when i click on the link, I am not getting any log. No Url or anything. Updated the question with logcat – Vamsi Challa Mar 01 '16 at 10:09
  • I tried your suggestion just now. But, no use. I am getting the URL for other link clicks, for example on a button click where the webview is loading a new webpage. But, no URL is getting logged for the . Same logcat output even now. – Vamsi Challa Mar 01 '16 at 10:23
  • So you're saying it's attempting to download the file without sending a request? That isn't possible, so something must be intercepting the event before the client can handle it – Nick Cardoso Mar 01 '16 at 10:26
  • Not sure what's happening, but got to work on some other things. Thanks for your help. I will award you the bounty as a token of my appreciation. – Vamsi Challa Mar 01 '16 at 10:29
  • Thankyou. Good luck with figuring this out later – Nick Cardoso Mar 01 '16 at 10:30
  • @VamsiChalla did you not find an answer of your own, or here that you can accept, to close this question? – Nick Cardoso Mar 22 '16 at 11:45
0

Most of the work can be done at the web page side itself. You have to write java script to identify which device is accessing the page (mobile, desktop etc) if its mobile then use java script binding technique to call the native android code to show Toast message.

http://developer.android.com/guide/webapps/webview.html

WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");

WebAppInterface.java

public class WebAppInterface {
    Context mContext;

    /** Instantiate the interface and set the context */
    WebAppInterface(Context c) {
        mContext = c;
    }

    /** Show a toast from the web page */
    @JavascriptInterface
    public void showToast(String toast) {
         Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }
}

YourHTML Page (this sample got a button click)

<input type="button" value="Say hello" onClick="showAndroidToast('Hello  
             Android!')" />

    <script type="text/javascript">
    function showAndroidToast(toast) {
         Android.showToast(toast);
    }
</script>
Guru_VL
  • 402
  • 3
  • 6