Basic internal links don't work in honeycomb app?

Internal links do not seem to be working in Android version 3 in my published app. My app targets Froyo at this point.

The app works fine on tons of phones, but my new Galaxy Tab can’t handle the internal links!! It can handle them within an html page, ie:

  • How can a service listen for touch gestures/events?
  • AppCompat Actionbar styling
  • In gridview adapter, getView(position == 0) was invoked too many times to measure layout when setImageBitmap() in a loader
  • GCM register didnot work on my emulator
  • How to get Activity's content view?
  • how take screen shot of currently playing video?
  • <a href="#faq">Go to faq</a>  <!-- goes to FAQ link -->
    

    Goes to the tag lower on the same page:

    <a name="faq" id="faq"></a>  
    

    However from a another html file, ie the index page, the link no longer works in Honeycomb:

    <a href="mainpage.html#faq">FAQ</a>  <!-- goes to error page -->
    

    Also, if I go to an internal link, and from there follow a link to another page, then hit the back button, (it is overridden to go to previous webview page) you get the same error ie:

    The webpage at file:///android_asset/folder/mainpage.html#faq might be temporarily    down or it may have moved permanently to a new web address
    

    WTF! The webview was just on the page, but you hit back 1 second later, and it can’t find it. Nor can it link from another html page, but it all works fine in 1.x, 2.x, just not 3.1 (have not tried 3.0)

    NOTE: I have seen this almost identical question:
    android_asset not working on Honeycomb?
    But there are no spaces in my asset path.

    I have tried with and without the webclient, and tried the DOM and cache settings to no avail. Here is an example of what I currently have in oncreate:

            browser = new WebView(this);
    //  browser = (WebView) findViewById(R.id.webkit);  // tried with XML and without
        browser.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        browser.getSettings().setJavaScriptEnabled(true);
        browser.getSettings().setPluginsEnabled(true);
    //  browser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    //  browser.getSettings().setUseWideViewPort(true);
        browser.setBackgroundColor(Color.parseColor("#333333"));
        browser.setInitialScale(1);
        browser.getSettings().setBuiltInZoomControls(true);
    
    
        final Activity MyActivity = this;
        browser.setWebChromeClient(new WebChromeClient() {
    
            public void onProgressChanged(WebView view, int progress) {
                // Make the bar disappear after URL is loaded, and changes
                // string to Loading...
    
                setProgressBarIndeterminateVisibility(true);
    
                MyActivity.setTitle("  Loading . . . " + progress + "%");
                MyActivity.setProgress(progress * 100); // Make the bar
    
                if (progress == 100) {
                    setTitle("  APP TITLE YADA YADA");
                    setProgressBarIndeterminateVisibility(false);
                }
            }
        });
        browser.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
            {
                // Handle the error
            }
    
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url)
            {
                view.loadUrl(url);  // note I tried with and without overriding this 
                return true;
            }
    
        });
        setContentView(browser);
    
        browser.loadUrl("file:///android_asset/folder/page.html");
    

  • MonoDroid VS Java in android development?
  • android-How to run Service in different thread than main thread?
  • android RelativeLayout change height programmatically
  • String Encoding problem in Webview
  • Testing ViewPager with Espresso. How perfom action to a button of an Item?
  • Can't create handler inside thread which has not called Looper.prepare()
  • 2 Solutions collect form web for “Basic internal links don't work in honeycomb app?”

    Here is the solution I use. Works the same on all Android platform (tested on all 1.6 to 4.0.1)

    Load the file as you would normally, without the anchor point. E.g.:

    webview.loadUrl("file:///android_asset/file.html");
    

    Load the URL without the anchor point (e.g. file:///android_asset/file.html), and add:

    webview.setWebViewClient(new WebViewClient()
    {
        public void onPageFinished(WebView view, String url)
        {
            if (this.anchor != null)
            {
                view.loadUrl("javascript:window.location.hash='" + this.anchor + "'");
                this.anchor = null;
            }
        }
    });
    

    where anchor is the anchor point you want to jump to.

    you have to make sure javascript is enabled:

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

    This is for loading the file into the webview.
    Now if you want to catch internal links that are now broken, as suggested in the other answer, override the onReceivedError method and insert do something like:

        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
        {
            int found = failingUrl.indexOf('#');
    
            if (found > 0)
            {
                anchor = failingUrl.substring(found + 1, failingUrl.length());
                view.loadUrl(failingUrl.substring(0, found));
            }
        }
    

    Here is my workaround code so the bug is transparent to the user.
    Define the WebViewClient for the browser, and include something like the following for onReceivedError:

            @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
        {
            if (failingUrl.contains("#")) {
                Log.v("LOG", "failing url:"+ failingUrl);
                final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
                if (sdkVersion > Build.VERSION_CODES.GINGERBREAD) {
                    String[] temp;
                    temp = failingUrl.split("#");
                    view.loadUrl(temp[0]); // load page without internal link
    
                    try {
                        Thread.sleep(400);
                    } catch (InterruptedException e) {
    
                        e.printStackTrace();
                    }
                }
    
                view.loadUrl(failingUrl);  // try again
            } else {
                 view.loadUrl("file:///android_asset/tableofcontents.html");
            }
        }
        });
    

    This tricks the webview to first load the page without the #link, then sleep for .4 of a second, and then load the full URL again. I have chosen to do this trick for tablets only by sdkVersion. If there is any other error I load another page, the tableofcontents.html. This works to fix the problem on my Galaxy Tab.

    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.