6

I'm writing a game with javascript. This app runs well on my browser (fast), but I have some trouble to run that with android webview.

  1. The time to start the app takes 5s or more (I think that is kind of slow, but maybe that is normal?)
  2. In the menu of the game I have a method like:

    this.showCredits = function() {
    document.getElementById('core-credits-layer').style.display = 'block';
    document.getElementById('core-credits').style.display = 'block';
    var parent = this;
    
    $.ajax({
        url: 'content/credits.html',
        dataType: 'html',
        success: function(data, status, response) {
            var  now = new Date();
            var s = now.getSeconds()-parent.test.getSeconds();
            console.log('success ajax: '+s);
            document.getElementById('core-credits').scrollTop = 0;
            document.getElementById('core-credits').innerHTML = response.responseText;
            console.log('finished');
        },
        error: function() {
            console.error('failed fetch credits');  
        }
    });
    }
    

    So the console log ("finished", last line in success()), comes immediately after clicking the menu "credits". But it can takes 6s (more or less) until I see the the div #core-credits. In my browser, I see #core-credits immediately after clicking. But the 2nd time clicking on that menu point I get the div after 1-2s. I don't now what that is, I don't think so, that is a caching thing, because I get into the success() callback really fast.

Java side:

    public void onCreate(Bundle savedInstanceState)
{
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Context context = this.getApplicationContext();

    SharedPreferences wmbPreference = PreferenceManager.getDefaultSharedPreferences(this);
    boolean isFirstRun = wmbPreference.getBoolean("FIRSTRUN", true);
    if(isFirstRun) {
        this.copyAudioFiles(context);
    }

    WebView mWebView = (WebView) findViewById(R.id.webview);
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.getSettings().setDomStorageEnabled(true);
    mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

    String data = context.getFilesDir().getPath();
    mWebView.getSettings().setDatabasePath(data+"data/"+this.getPackageName()+"/databases/");
    mWebView.getSettings().setAllowFileAccess(true);
    mWebView.setWebChromeClient(new WebChromeClient());
    String data_root = Environment.getExternalStorageDirectory()+"/"
        +this.getPackageName();
    mWebView.loadUrl("file:///android_asset/www/index.html?system=android&" +
        "data_root="+data_root);  
}

I have this performance problems on my virtual tablet device in eclipse and also on my real asus tablet.

Also animations (jquery show('slow')) are sometimes really slow or broken. For example (It is a card game), a player becomes 9 cards with the show('slow') animation, every 2nd or 3rd time I get 3 or 8 cards but not 9^^.

All this things above are working well on browsers like chromium or firefox. I'm working with Android 4.1.

Activate hardware acceleration didn't help. There are various posts about this rendering problem with webview, but only with the hardware accelaration solution, which didn't help.

Philzen
  • 3,945
  • 30
  • 46
raffis
  • 546
  • 1
  • 5
  • 18

5 Answers5

5

Having gone through the process of developing several apps using Hybrid Mobile App frameworks in HTML5/JS on Android, i'm afraid there isn't a silver bullet that will fix all performance issues. Generally speaking, Javascript performance is not the problem, the problem is frequent and maybe even wasteful changes/modifications to the DOM and a over-use of CSS3 effects which slow the FPS down like box-shadow on Android.

Something which might help, is to use CrossWalk as your WebView rather than the stock WebView component. This means you can get the latest version of Chrome inside your app without having to rely on older versions of the system WebView component. You should observe a performance and stability improvement as you can gain all the benefits of the software improvements to WebKit.

https://crosswalk-project.org

Secondly, consider using a framework which avoids frequent changes to the DOM like React which has a virtual DOM.

http://facebook.github.io/react/

React isn't the only framework to provide this and there are other solutions which aim to provide performance improvements in this area like Famous.

http://famous.org

Lastly, choosing your frameworks to build your app on top of is for me, the most important step. Despite all the investment in improving performance of browsers, they all vary in performance in different areas, so best to hedge your bets at the beginning and pick frameworks which suit the problem you are trying to solve.

Appreciate you may have moved on from this, so hoping this advice will help others.

#lovejavascript, #hatebrowsers

Daniel Maclean
  • 779
  • 10
  • 21
4

Forget about HW acceleration in this case - it's a false friend. In most cases it's even slower than software rendering.

But there are many small things you can optimise:

Write faster javascript

  • Always use selector caching, where applicable (there should be only a single occurence of document.getElementById('core-credits') in your code
  • Group / decouple (see next point or use setTimeout directly) code execution and DOM manipulation (which always triggers redraws on single elements or - even worse - a reflow of the document)
  • In some apps i saw good results using the requestAnimationFrame Polyfill for dom manipulations - won't necessarily lead to a higher framerate, but in my case it allowed me to properly "fling" an openlayers map (instead of the device just not reacting to the touchmove)

Be Android friendly

  • Just like intel appframework (formerly jqmobi ui) does, make heavy use of css3 transformations rather than trying to jquery-style "tick" animations
  • Removing border-radius and instead utilising a transparent png approach
  • Other costly renderings on Android are supposed to be: (-webkit-)box-shadow, text-shadow and all kinds of gradients (which again one can exchange for old-school png's)

Hope this helps - will try to elaborate more, resp. rectify information as i continue to fight android webview sluggishness in my own apps currently.

Community
  • 1
  • 1
Philzen
  • 3,945
  • 30
  • 46
  • Hmm css3 things like border-radius or box-shadow aren't that problematic. Huge problems are $.show('slow') or simular things. Also scrolling content or just search an id in the dom and set style.display = 'block' is kind of slow... – raffis Jun 10 '13 at 11:22
  • I don't think so, i can write the code much better/faster, (Maybe more selector caching), I guess Android webview is just that slow. Bummer! Bad html5 app future. – raffis Jun 10 '13 at 11:26
  • Scrolling content that has gradients, border-radius`s etc... is definately slow. Default selector actions (get element and show/hide/change styles) should be blazingly fast, at least to my experience with with jQMobi or JQuery 2.x (everything else will surely be slower, as it's a total waste of code and performance in a webkit-only environment) – Philzen Jun 11 '13 at 18:35
1

did you enable hardware accelaration in your manifest?: http://developer.android.com/guide/topics/graphics/hardware-accel.html ?

Mikael
  • 2,355
  • 1
  • 21
  • 45
0

For the animations try adding this to the elements css:

transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

This has been the only speedhack that really had a effect on my webview. But be careful not to overuse it! (you can read more about the hack in this article.)

I would also recomend doing the animations i css

Erex
  • 1,625
  • 1
  • 17
  • 21
0

Browser has to repaint the ui in Dom alterations. It doesn't affect us much on desktops but really clogs animations on mobiles. You should consider using css3 transitions as they are handled by gpu and are more performant. If you don't mind using a javascript library I would recommend you to try out famo.us It claims to bebe able to give 60fps animations. Which seems to be indeed true.

Chromonav
  • 773
  • 5
  • 11