Back to Home

Crosswalk Project is a replacement for Android WebView. Integration issues

android · android development · webview · webview must die · crosswalk

Crosswalk Project is a replacement for Android WebView. Integration issues

    Crosswalkproject

    In this article I will end my story about the Crosswalk Project (the first part you can find here ). I will tell in more detail about my experience with Crosswalk integration, some subtleties when working with it, the problems encountered and their possible solutions.

    The first and perhaps most obvious solution to all of these issues is changing the Crosswalk code to fit your needs. This is possible because the project is open and you can even help its authors. However, this is not always necessary and may cause additional difficulties. In the described examples, I do not consider this option, but it is useful to study the code of the base classes.

    Controlling page loading in XWalkView.


    Perhaps the second most important thing in Crosswalk, after its speed, is the predictability of callback calls. The ability to focus on the logic of calls and have a single algorithm for all versions of Android is just fine. The difficulties with loading control in the system WebView are well described in this article .

    Like the system class, XWalkView has two helper classes that can receive calls while loading and working with XWalkView - XWalkUIClient and XWalkResourceClient. As I wrote earlier, they do not directly correspond to the system WebChromeClient and WebViewClient, the methods in them are distributed somewhat differently. However, for myself, I set an approximate match as WebChromeClient == XWalkUIClient and WebViewClient == XWalkResourceClient.

    XWalkUIClient also contains methods:
    • onPageLoadStarted - informs about the start of loading the main frame.
    • onPageLoadStopped - informs about the end of loading the main frame.

    and:
    • onConsoleMessage
    • onReceivedTitle
    • onConsoleMessage
    • onRequestFocus
    • shouldOverrideKeyEvent

    As you can see, there are methods included in both the WebViewClient and WebChromeClient interfaces, but, in general, the XWalkUIClient contains methods that are important for the UI.

    XWalkResourceClient including contains:
    • onDocumentLoadedInFrame - informs that an HTML document has been received and processed, is called without waiting for loading css, images, etc. NB! I note that the method is described in Javadoc and implemented in the master branch, but is now absent in the class during integration.
    • onLoadStarted - informs that the loading of the resource at the specified url has begun.
    • onLoadFinished - informs that the loading of the resource at the specified url has completed.
    • onProgressChanged - informs about the percentage of page load.
    • shouldInterceptLoadRequest - similar to the system callback, allows the client to return data for the indicated url.
    • shouldOverrideUrlLoading - similar to the system callback, allows the client to take control before loading the resource.

    The sequence of calling the main callbacks looks like this:
    • shouldOverrideUrlLoading - for the specified url;
    • onPageLoadStarted;
    • shouldInterceptLoadRequest - loading the main page;
    • onLoadStarted - loading the main page (duplicates shouldInterceptLoadRequest);
    • shouldInterceptLoadRequest paired with onLoadStarted - loading resources for each resource;
    • onPageLoadStopped;
    • onLoadFinished.

    This sequence will be similar for the url loaded using the WXalkView method, and for following the link on the page and even when the download is stopped using stopLoading ().

    The sequence for loading a page with a redirect looks almost the same:
    • shouldOverrideUrlLoading - for the specified url;
    • onPageLoadStarted;
    • shouldInterceptLoadRequest - loading the main page;
    • onLoadStarted - loading the main page;
    • shouldOverrideUrlLoading - for the url specified in the redirect;
    • onPageLoadStarted;
    • shouldInterceptLoadRequest paired with onLoadStarted - loading resources;
    • onPageLoadStopped;
    • onLoadFinished.

    As you can see, when switching to the redirect, we received additional calls of the same starting callbacks and, in fact, the logic in this case was not violated either.

    Additionally, you can specify that the onPageLoadStopped method has the following signature:
    onPageLoadStopped(XWalkView view, java.lang.String url, XWalkUIClient.LoadStatus status);
    

    An additional parameter of the type XWalkUIClient.LoadStatus gives quite important information about how the download ended and has 3 options:
    • CANCELLED - in case of stopLoading () call;
    • FAILED - in case of a download error;
    • FINISHED - Normal download termination.

    Not without a couple of oddities in the behavior of Crosswalk. For example, the onLoadFinished method is called only once after loading the entire page, and even after onPageLoadStopped. The logic assumes that the onLoadFinished call must match the onLoadStarted call that occurs for each resource, but now it is not.

    It is also possible that a double call of a pair of final methods onPageLoadStopped and onLoadFinished occurs. I found a mention of this behavior for Crosswalk version 11, but obviously this problem has not been solved so far.

    Handling events from the screen and buttons.


    One of the first problems you will encounter when integrating XWalkView will be the handling of screen and keyboard events (specifically, the Back button). XWalkView, like the onActivityResult and onNewIntent methods, implements the method: dispatchKeyEvent (KeyEvent event). It intercepts an event from the Back button to switch from full-screen mode and go through the browser history. Accordingly, you cannot receive this event if you use methods:
    public boolean onKeyUp(int keyCode, KeyEvent event);
    public void onBackPressed();
    

    A solution could be to handle this event also in dispatchKeyEvent (KeyEvent event). It is also useful to know if you want to implement your own navigation history navigation.

    A similar problem awaits you if you want to use the onTouchEvent listener for your XWalkView. The solution is similar to the above - implement event handling in dispatchTouchEvent (MotionEvent event).

    Examples have been added to the test project available on GitHub .

    Work with cookie storage.


    An important point in the operation of the browser and WebView is the processing of cookies. For example, you want to load some page not through XWalkView, but display it in it and give the user the opportunity to work with it. The page can set its cookies and for normal operation they will be needed in XWalkView.

    Crosswalk has a special component XWalkCookieManager , which actually deals with the storage and operation of cookies. Very strange, but it is not described in Javadoc, although it is public and available for use. Implementation and comments on class methods can be found here.

    XWalkCookieManager, like the Crosswalk cache, is the same for all XWalkView instances in your application. The class is quite simple to use and allows you to add and receive cookies for a specific address, clear the storage, etc. Initialization example:
    mXCookieManager = new XWalkCookieManager();
    mXCookieManager.setAcceptCookie(true);
    mXCookieManager.setAcceptFileSchemeCookies(true);
    

    However, the simplicity of its implementation has some problems. For example, a method for setting a cookie looks like this:
    public void setCookie(String url, String value);
    

    Accordingly, you will not be able to specify the lifetime for the cookie, and domain and path for the cookie will be obtained from the specified url, but with some unpleasant nuances.

    For example, you want to set a cookie for the address m.vk.com and assume that the cookie set will be valid for the address login.vk.com , but in our case it is not. In order for the XWalkCookieManager to work properly, you need to set a cookie for the .vk.com address .

    It is also stated that the XWalkCookieManager should update the cookie if you install an existing one in the store, but I have observed that sometimes it duplicates the values. Obviously, there are some problems parsing value during installation. Therefore, it is worth checking once again that the classes work correctly if you use it.

    As a simple example of working with XWalkCookieManager, the test project implements the synchronization method with CookieManager.

    Getting WebSettings and installing them.


    As I wrote earlier, WebSettings are not available when working with XWalkView and have predefined settings. More precisely, Crosswalk has an analogue of this class - XWalkSettings , you can learn its methods here. An exception was made for some parameters and they are made in the interface of the XWalkView class itself. For example, now you can install the User-Agent you need.

    However, it may be necessary to fine-tune it. It may also be necessary, as in my case, to get the User-Agent used by XWalkView itself. In this case, you can take the opportunity to get it through reflection.

    The XWalkView class itself is an add-on for the XWalkViewInternal implementation .and connects to it via bridge through reflection. XWalkViewInternal has a public getSettings () method, which we can use:
    Method ___getBridge = XWalkView.class.getDeclaredMethod("getBridge");
    ___getBridge.setAccessible(true);
    XWalkViewBridge xWalkViewBridge = null;
    xWalkViewBridge = (XWalkViewBridge) ___getBridge.invoke(webView);
    XWalkSettings xWalkSettings = xWalkViewBridge.getSettings();
    

    As an example of obtaining XWalkSettings and working with it, the test project implements the method of obtaining User-Agent.

    Getting an XWalkView Image.


    Since XWalkView uses SurfaceView or TextureView for rendering, there is no way to get its image using standard methods. For example, this option works for the system WebView, but does not work for XWalkView:
    View view = mWebView.getRootView();
    view.setDrawingCacheEnabled(true);
    Bitmap b = Bitmap.createBitmap(view.getDrawingCache());
    view.setDrawingCacheEnabled(false);
    

    This happens because standard view methods, such as getDrawingCache () or draw (), work with the software layer, while XWalkView uses the hardware layer. That is why developers are asked to set the flag android: hardwareAccelerated = "true" for applications using Crosswalk. By the way, now it is installed by default and there is no need to register it separately.

    It is possible to get an XWalkView image when using TextureView as the basis, where there is a getBitmap () method. In short, for this you need to find the target TextureView in the tree and call this method on it already. An example implementation is also available in a test project.

    Minor nuances.


    In addition, there are a few minor points that you may also encounter during the integration process:
    • If you are replacing the system WebView in an old project and using the JavascriptInterface annotation, be sure to fix the import. Otherwise, you will receive errors during the execution of JavaScript code. Respectively:
      import android.webkit.JavascriptInterface; // remove
      import org.xwalk.core.JavascriptInterface; // add
      

    • If you use several XWalkViews, use it in fragments or in some other, more complex conditions than in the example. In this case, a situation may arise when it will be necessary to directly call methods to awaken the XWalkView timers, after resuming work with it:
      public void resumeTimers();
      public void onShow();
      



    conclusions


    Using Crosswalk in development is quite simple and convenient, especially considering the open source code. A good community and a fairly large distribution of the project will solve most of the problems.

    If you support Android 4.0+ and want more predictable performance of your code on all versions of Android, then I definitely recommend Crosswalk.

    If you support Android from version 4.4 and even more so 5.0, then I would think about using Crosswalk in my projects. The lack of some new features of the system WebView can complicate your life.

    I hope my experience will help you decide what to use as a WebView for your project :).

    Read Next