2013年7月16日 星期二

Resolve cross-domain error

The scheme is that I call a JS function after loading a JS file from web, and in the JS function it in the end sends out a HTTP GET request to obtain a web page which I use for further tasks. I run into a problem when the HTTP GET request is sent and the error message shows:

XmlHttpRequest error: Origin null is not allowed by Access-Control-Allow-Origin

This is a common CORS issue, which is short for Cross-Origin Resource Sharing. I surfed the internet a lot and found some possible answers to this question. One of them is to get the server side to set up a "Access-Control-Allow-Origin: *" text in the header to tell clients that it allows CORS. However, in my case I have not got to the point of completing sending out a request, but rather got rejected before it. This could be a local check for origin, so I checked the development guide for possible web settings and found this one:

void setAllowUniversalAccessFromFileURLs(boolean flag)
Sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin.

And it works ! The following is part of my code which points out my use of it:

notice: The setting is true by default under API level 16 and false by default equivalent or above API level 16. The API is only defined after API level 16.

[JavaScriptHandler activity]
in pptv.js it uses the following Android interface, so I create them in this activity to save the result:
atv.loadXML(atv.parseXML(doc));

public class JavaScriptHandler {
    Webview_test parentActivity;
   
    public JavaScriptHandler(Webview_test activity) {
        parentActivity = activity;
    }

    @JavascriptInterface
    public String parseXML(String val){
        System.out.println("parseXML...");
        return val;
    }
   
    @JavascriptInterface
    public void loadXML(String val){
        System.out.println("loadXML...");
        this.parentActivity.javascriptCallFinished(val);
    }
}


[WebView activity]
public class Webview_test extends Activity {
    WebView myWebView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview_test);
        // Show the Up button in the action bar.
        setupActionBar();
        Intent intent = getIntent();
        String url = intent.getStringExtra("xml_url");
        myWebView = (WebView) findViewById(R.id.webview);
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.getSettings().setBuiltInZoomControls(true);

        if(android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
           
myWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);

        }
        myWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                        System.out.println("got here!");
                        return super.onJsAlert(view, url, message, result);
               }
        });  
        myWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                view.loadUrl("javascript:(function() { "
                        + " document.bgColor='#FF0000';" //turns to red the background color
                        + " var script=document.createElement('script'); "
                        + " script.setAttribute('type','text/javascript'); "
                        + " script.setAttribute('src', 'http://trailers.apple.com/js/pptv.js'); "
                        + " script.onload = function() {"
                        + "       pptvLoad();"
                        + "};"
                        + " document.getElementsByTagName('head')[0].appendChild(script); "
                        + "})()");
            }
        });
        myWebView.addJavascriptInterface(new JavaScriptHandler(this), "atv");
    }
...
    public void javascriptCallFinished(String val){
         System.out.println(val);
    }
...   
    public void testAndroid2JS(View view) throws IOException
    {
        myWebView.loadUrl("file:///android_asset/testalert2.html");
    }
}


Reference links
http://stackoverflow.com/questions/14825943/setallowuniversalaccessfromfileurls
cross-site HTTP request (CORS)
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redirectlocale=en-US&redirectslug=HTTP_access_control
Introduction to XMLHttpRequest class in Javascript
http://ajaxpatterns.org/XMLHttpRequest_Call
development guide
http://developer.android.com/reference/android/webkit/WebSettings.html

沒有留言:

張貼留言