PhoneGap/Cordova App for Android has a very long start time

Hi Developers,

I have packaged my Enyo2 webapp as Android app with Phonegap and I have published in the google play store. You can find the app here. I have used the Adobe Phonegap build service.

A lot of users means that my app have a long start time. What I can do?

At first I have setup a new local cordova android project. After that I have added the last deployed version of my enyo webapp into the folder assets/www.

Here ist my new index.html:

<!DOCTYPE html>
<html>
	<head>
		<title>Mensa Chemnitz</title>
		<link rel="shortcut icon" href="assets/favicon.ico">
		<!-- meta -->
		<meta http-equiv="Content-Type" content="text/html; charset=utf8">
		<meta name="apple-mobile-web-app-capable" content="yes">
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
		<!-- css -->
		<link href="build/enyo.css" rel="stylesheet">
		<link href="build/app.css" rel="stylesheet">
		<!-- js -->
		<script src="build/enyo.js"></script>
		<script src="build/app.js" onerror="alert('No application build found, redirecting to debug.html.'), location='debug.html';"></script>
		<script src="cordova-2.3.0.js"></script>
		<!-- webfont -->
		<link href='http://fonts.googleapis.com/css?family=Courgette' rel='stylesheet' type='text/css'>
		<script>
			function onBodyLoad() {
				document.addEventListener("deviceready", onDeviceReady, false);
			}
			
			// PhoneGap is loaded and it is now safe to make calls PhoneGap methods
			function onDeviceReady() {
				// tell enyo to listen for backbutton event
				enyo.dispatcher.listen(document, "backbutton");
				new App().renderInto(document.body);
			}
		</script>
	</head>
	<body onLoad="onBodyLoad();" class="enyo-unselectable">
	</body>
</html>

And the Android main java class:

public class MensaChemnitzAndroid extends DroidGap
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        super.setIntegerProperty("splashscreen", R.drawable.ic_launcher);
        super.loadUrl("file:///android_asset/www/index.html", 5000);
    }
}
You can see I have added a splashscreen. The app works in the andoid emulator but the start time is very long.

Splashscreen: 5 seconds
white screen: 10 seconds
app loaded

I can say that the reason is not the google webfont.

Thanks in advance,
Cheers Björn

Comments

  • Can you add some logging (say storing time values at various points and dumping them on startup) at the various script parts to see if it's script loading/parsing that's taking a long time?
  • Hi Ben,
    you can download the log file here: https://www.dropbox.com/s/jchh79tvf3pj7zf/log.txt

    Here the new index.html with log entries:

    <!DOCTYPE html> <html> <head> <title>Mensa Chemnitz</title> <link rel="shortcut icon" href="assets/favicon.ico"> <!-- meta --> <meta http-equiv="Content-Type" content="text/html; charset=utf8"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <!-- css --> <link href="build/enyo.css" rel="stylesheet"> <link href="build/app.css" rel="stylesheet"> <!-- js --> <script src="build/enyo.js"></script> <script src="build/app.js" onerror="alert('No application build found, redirecting to debug.html.'), location='debug.html';"></script> <script src="cordova-2.3.0.js"></script> <!-- webfont --> <link href='http://fonts.googleapis.com/css?family=Courgette' rel='stylesheet' type='text/css'> <script> function onBodyLoad() { console.log("onBodyLoad was called"); document.addEventListener("deviceready", onDeviceReady, false); } // PhoneGap is loaded and it is now safe to make calls PhoneGap methods function onDeviceReady() { console.log("onDeviceReady was called"); // tell enyo to listen for backbutton event enyo.dispatcher.listen(document, "backbutton"); new App().renderInto(document.body); console.log("enyo was rendered into document body"); } </script> </head> <body onLoad="onBodyLoad();" class="enyo-unselectable"> </body> </html>
    Between

    console.log("onDeviceReady was called");
    and

    console.log("enyo was rendered into document body");
    exist 8 seconds and the screen is white.

    What can I do against this white screen? And what can I do to decrease the long start time?

    Thanks in advance
    Cheers Björn
  • Put the cordova js as the first script to be loaded before even the css. This should speed it up.
  • Unfortunately not.

    Here the changed lines in index.html:

    <title>Mensa Chemnitz</title> <link rel="shortcut icon" href="assets/favicon.ico"> <!-- meta --> <meta http-equiv="Content-Type" content="text/html; charset=utf8"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <!-- cordova --> <script src="cordova-2.3.0.js"></script> <!-- css --> <link href="build/enyo.css" rel="stylesheet"> <link href="build/app.css" rel="stylesheet"> <!-- js --> <script src="build/enyo.js"></script> <script src="build/app.js" onerror="alert('No application build found, redirecting to debug.html.'), location='debug.html';"></script> <!-- webfont -->
    Here the results of logcat:

    01-30 21:47:31.211: D/MensaChemnitz(1150): onDeviceReady was called
    01-30 21:47:31.241: I/App(1150): WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!
    01-30 21:47:32.621: D/DroidGap(1150): onMessage(spinner,stop)
    01-30 21:47:36.751: D/dalvikvm(1150): GC_CONCURRENT freed 235K, 5% free 8449K/8839K, paused 5ms+25ms, total 74ms
    01-30 21:47:36.751: D/dalvikvm(1150): WAIT_FOR_CONCURRENT_GC blocked 55ms
    01-30 21:47:37.381: D/dalvikvm(1150): GC_FOR_ALLOC freed 42K, 3% free 8801K/9031K, paused 36ms, total 56ms
    01-30 21:47:39.660: D/MensaChemnitz(1150): enyo was rendered into document body
    Thanks for your reply
    Cheers Björn
  • Eight seconds to render your application is pretty unreasonable. Since the logging is synchronous, you know its not waiting on any async logic, so it's likely something in your component hierarchy. I do see a lot of time being spend on garbage collection, so there could be some sort of extreme memory usage that triggers that. One suggestion is adding a console.log in your local copy of enyo.Component.create after the call to ownerChanged outputting "this.id". That will log every component built as part of your app startup and might point to where you have too many components or where one's creation is taking a long time.
  • Hi Ben,

    I have add console.log entries to my app.js (create and rendered function) and cleaned my app a little bit. Here the results:

    01-30 23:12:30.110: D/MensaChemnitz(1820): onDeviceReady was called
    01-30 23:12:30.110: I/App(1820): WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!
    01-30 23:12:30.151: D/MensaChemnitz(1820): 1
    01-30 23:12:31.590: D/DroidGap(1820): onMessage(spinner,stop)
    01-30 23:12:32.231: D/MensaChemnitz(1820): 2
    01-30 23:12:32.251: D/MensaChemnitz(1820): 3
    01-30 23:12:32.261: D/MensaChemnitz(1820): 4
    01-30 23:12:32.261: D/MensaChemnitz(1820): 5
    01-30 23:12:32.271: D/MensaChemnitz(1820): 6
    01-30 23:12:32.271: D/MensaChemnitz(1820): 7
    01-30 23:12:32.281: D/MensaChemnitz(1820): 11
    01-30 23:12:32.281: D/MensaChemnitz(1820): 12
    01-30 23:12:32.291: D/MensaChemnitz(1820): 13
    01-30 23:12:32.291: D/MensaChemnitz(1820): 14
    01-30 23:12:32.301: D/MensaChemnitz(1820): 15
    01-30 23:12:32.710: D/dalvikvm(1820): GC_CONCURRENT freed 228K, 5% free 8445K/8839K, paused 4ms+15ms, total 79ms
    01-30 23:12:33.111: D/MensaChemnitz(1820): 16
    01-30 23:12:34.041: D/MensaChemnitz(1820): 17
    01-30 23:12:34.060: D/MensaChemnitz(1820): 18
    01-30 23:12:34.191: D/MensaChemnitz(1820): 19
    01-30 23:12:34.191: D/MensaChemnitz(1820): enyo was rendered into document body
    Yes, the app need 4 seconds now.

    create: function() { console.log("1"); this.inherited(arguments); console.log("2"); DateModel.initialize(); console.log("3"); CanteenModel.initialize(); console.log("4"); AppModel.initialize(); console.log("5"); AppModel.setExistsSmallScreen(); console.log("6"); // When ready... window.addEventListener("load",function() { // Set a timeout... setTimeout(function(){ // Hide the address bar! window.scrollTo(0, 1); }, 0); }); console.log("7"); // set visibility of food rotation buttons if (!AppModel.getExistsSmallScreen()) { console.log("8"); this.$.buttonBack.setStyle("visibility:hidden;"); console.log("9"); this.$.buttonPreviousFood.setStyle("visibility:hidden;"); console.log("10"); this.$.buttonNextFood.setStyle("visibility:hidden;"); } console.log("11"); // set canteen menu entries this.$.stranaCanteen.setContent(StraNaCanteen.name); console.log("12"); this.$.rhCanteen.setContent(ReichenhainerCanteen.name); console.log("13"); // set size of foodList //this.$.foodlist.setCount(50); console.log("14"); this.$.title.setContent(CanteenModel.getCanteenName() + " - " + this.formatDate(DateModel.getCurrentDate())); console.log("15"); }, rendered: function() { console.log("16"); this.inherited(arguments); console.log("17"); this.cleanContentPanel(); console.log("18"); this.setIndex(0); console.log("19"); },
  • Hi Ben,

    I have added the line
    console.log("Create component name:" + this.name + " id:" + this.id);
    to my enyo.js file (into create function of the kind enyo.Component).

    Additional I have delete all log entries of my app.js. Finally I have only 2 log entries (start, end) in the index.html.
    function onBodyLoad() {
    	console.log("Start");
    	document.addEventListener("deviceready", onDeviceReady, false);
    }
    			
    // PhoneGap is loaded and it is now safe to make calls PhoneGap methods
    function onDeviceReady() {
    	// tell enyo to listen for backbutton event
    	enyo.dispatcher.listen(document, "backbutton");
    	new App().renderInto(document.body);
    	console.log("End");
    }
    I have updated the log.txt on dropbox. You can find here: https://www.dropbox.com/s/jchh79tvf3pj7zf/log.txt

    I have resolved the white screen issue with the defining of a new css class in the body tag.

    What can I do to increase the start time of my app?

    Thanks in advance
    Cheers Björn
  • My thoughts: 4 seconds isn't unreasonable on an emulator. Typically they are much slower than devices. However, what if you moved the initialize() functions in your create method to the rendered handler? That would provide a screen more quickly I would think.
  • Looking at the log, nothing was too surprising. You might want to see about simplifying some composite objects by generating your own innerHTML instead of a bunch of simpler controls. The GC in the middle of initializing the app is eating a lot of time too. It also looks like about 1/2 second of delay is from waiting for the data response that populates your repeater.
  • bjabja
    edited January 2013
    Hi @strider73, Rendered handler? Do you mean the rendered function?
  • Hi @unwiredben and @strider73, thanks for your responses.
  • Today, I have tested my app on a Nexus 7. The start time is ok now. 2 seconds.

    Thanks
  • Now, the new version is available in Google Play Store:
    Tweet
Sign In or Register to comment.