When and how does a PWA update itself? - android

As far as I know, once you click "add to homescreen" on a PWA's website, the browser generates an .apk using the provided manifest file and sources and installs it like a normal app.
I noticed that when I update the website, the app also displays the updated content which suggests that the app is just a wrapper for accessing the website. I also noticed that the update to a website is not displayed instantly, I assume this is due to internal caching.
My question is, are my assumptions correct? Or more generally, when and how are PWAs updated and is there a way to force an update on a client machine?

No cache scenario (No Service worker): Your PWA app will be cached only when you use Service worker. Manifest.json will help adding your web app to home screen with a icon and open without address bar. If you don't have a service worker or if your browser don't support it, web page will be loaded fresh every single time. No Cache.
Cache-On Scenario (With Service worker): Assuming you have service workers configured, service workers can cache by lazy loading or prefetching the files that are configured for caching (You can include or exclude caching anything from html, CSS, images to JSON/XML API responses).
After the initial cache, service worker will use the cache to serve your apps network request based on cache approach you have implemented from below ones.
cache falling back to network
Network falling back to cache
Cache then network
Most apps choose to precache due to performance benefits and look for new files on loading, if any changes found will be loaded on next session or prompt user to refresh. With this solution, each file will have a long Hash string for each file cached by service worker. On load of each application, hash code from server will be fetched to match and find what file needs to be updated and the same will be updated in a separate service worker thread. You can notice this in network tab -> service worker response in chrome developer tools.
If you choose network-first approach, you can avoid showing old content on initial load, but loose significant performance benefits that comes with caching.

Only two events…
In essence, there are only two events that will automatically trigger a PWA update:
A change in the linked manifest.json; e.g. a changed icon file or a changed scope or start_url.
A one-character change in the controlling service-worker.js. Hence, if you store the version number in a const in this file and change it, an update of the PWA will be triggered.
When a change is detected, the new version will normally be activated only with the next PWA load. So, in all, two reloads are necessary to see a change.
How the update eventually is handled, is ultimately determined by the service-worker.js. Different update strategies may be defined in terms of the size and volatility of the PWA assets. It is also possible to activate a new service immediately.
However, there is one important caveat. Make sure that the browser cache expiry directive set by the .htaccess file of your asset server is set to a really short duration (e.g. hours) or even to none.
Failing to do so, will result in the browser not seeing any change for days to come in the manifest.json nor the service-worker.js.
More details about service worker behaviour are available from Google Web Fundamentals.

Related

Can a Mobile web app / pwa send HTTP requests while "minimized" on the phone?

If I open a web app using a web browser or a PWA by clicking the icon on my home screen, can that app still send HTTP requests while it's minimized?
I'm asking this because of say, for example, I want to check out a navigation app to navigate to somewhere but I still want the web app to update the user's location through HTTP requests while it's minimized.
Is it possible or does the app stop "working" while it's not in focus? Is it a service worker implementation needed?
You can achieve your task implementing a PWA. The Service Worker file will run in the background and keep running even when the user closes the app.
This is possible since the SW runs on a separate thread.
It is also possible to execute background sync, even though its support is quite limited:
You can let the service worker call the server to send the user's position if internet connection is available, otherwise this information can be stored in a local DB (eg. IndexedDB or Cloud Firestore) and then, once the users gets online again, the changes will be pushed to the server.
The nice thing by using Cloud Firestore is that the synchronisation is made out of the box for you. I wrote an article about the usage of Firestore with PWAs to overcome the limits of CACHE API. It is within a series of articles about PWAs, have a look st tit if you want to deepen the topic.

Design for downloading files before starting of an Activity

I have a use case where I want to download some files from the server and store them locally before starting another activity that is dependent on this file. This kind of design can be found on karaoke kind of applications where clicking on one song would
Load the required files from the server
Once the download is finished, open the required activity.
Let us assume that my app is a karaoke app. My question is how to design this flow. Basically, on clicking on one song, I want to show progress on the screen and when the download is finished, I want to move to the activity. Another requirement is that once I am inside the karaoke activity screen and playing a song, I have an option which leads to loading of another lesson. If a user uses that option, I want to again download the required files. Based on this requirement, should I:
Have the file loading thing as a separate activity?
OR
It can be used as Fragmentinside the activity where I choose a particular song. In this case, once entering the karaoke screen, if I choose an option which leads to downloading some files and reloading of this activity, is this the best design?
I would recommend two different approaches depending on how long you plan on keeping the data that you've downloaded. If it is single use than a bound service would be ideal. However, if you are planning on keeping the downloaded content for more than a single use, I would recommend you use a content provider and possibly a sync adapter(Depending on how frequent/predictable content downloading is). This combo would help guide you into not having to think about the 'design' as much(Since it is pretty standard at this point), plus it would provide a lot of features that you may/may not find useful: you can make your internal data 'public' via the content provider/authority(s), you can make an 'account' on the phone associated with your app so that the user can manage its syncing via the sync manager(actually via widgets/apps using the sync manager, but still), and most importantly a set of clean(ish)/standard means to interact with it/propagate UI, etc.
My simple version would be an Activity that spawns either a async-AIDL service with callback (which is in my opinion the only way to use a bound service) that would allow you to asynchronously design your 'starter' activity, its "currently downloading" spinner (which can get progress updates via the callback if you design it that way). Then once the download is complete then send the results (via a parcel file descriptor in the Intent's bundle) to the new activity that makes use of it.
However, if you are planning on using the data more than once, I'd recommend downloading the content like you did above, but then also store it in a content provider for easy access later. Providers also have a lot of nice associated functionality related to cursor loaders, etc. that will help keep a list of the content currently being stored nice and clean/up-to-date/dynamic/etc. However, this is a lot more work to setup once, then later it would save you time in reduced.
A sync adapter is best when the data to be downloaded is predictable, either based on user's account or temporally (such as someone having an account to download data from (email account, etc.) or when the target is fairly constant, but the data should be updated every hour or so(such as the current weather)). So this will depend a lot on your application's exact specifics.
Here is an assignment for an Android App Development course I wrote that is an even more simplified version of the first option (it has intent service + broadcast receiver for returning download results back to the Activity). Obviously since this is an assignment it has sections cut out to make skeleton code, but the documentation is ABSURDLY detailed and should be fairly easily implemented.
https://gitlab.com/vandy-aad-3/aad-3-assg-2/tree/master
Here is the extension of that assignment for that same course that focuses on implementing a simple content provider's 4 main methods (Create, Read, Update, & Delete). Everything else about the provider is given to you.
https://gitlab.com/vandy-aad-3/aad-3-assg-3/tree/master
Obviously the content being downloaded in both applications is probably not what you intended, but that is a simple swap to replace in what you do want.
Not to shill to hard, but here is the (free) Specialization that this course is a part of: https://www.coursera.org/learn/androidapps
Point one : Don't download video file within the Activity level. You can start a Service to handle it. Once the download function is finished you can start the second Activity. While download function is in progress you can show a ProgressBar
Point Two : Best Design is show a ProgressBar with percentage to user. Or disable the function. After download complete enable or start the second activity.

What is the lifecycle of an installed Progressive Web App on Android?

I have a strong Android background but I have recently developed a PWA that can be installed to a users device. I have noticed that when the app starts for the first time, the splash screen shows and then the app displays it's first page which is great. Now, if the app has been backgrounded for a while and I relaunch the app, it sometimes appears to display a white screen for a few seconds then the app kind of flickers and some aspects of the page reload, creating a jarring experience.
I am familiar with how lifecycles work in Android, saveInstanceState and all that jazz, but what is actually happening here with a PWA is backgrounded? I am unable to debug what is happening because it takes a long time to reproduce and the debugger needs to be attached before launching the app.
Are there any documents describing exactly what is happening with the lifecycle of an installed PWA and how to gracefully restore it when it has been backgrounded or background-killed?
You may look into this documentation. "Progressive Web Apps have to be fast, and installable, which means that they work online, offline, and on intermittent, slow connections. To achieve this, we need to cache our app shell using service worker, so that it's always available quickly and reliably." A service worker has a lifecycle that is completely separate from your web page. Based from this article, a service worker lifecycle usually has three stages:
The install stage, during which it is common to cache assets like stylesheets, client-side JavaScript, and so on.
When the install stage was successful, the activation step happens, during which any obsolete caches are deleted.
Then, the service worker is idle until it needs to deal with a request from the client code.
You may read the article for more information. Hope this helps!

Increase performance startup hybrid app

I have a problem, when i startup my hybrid app. It takes very long to load the first page. ~40 seconds.
I work with GWT, Google App Engine and RequestFactories. I detected, that the app makes several request to the server (~ 10 requests).
Now i wonder, how can i increase the performance of staring up my app.
Group all request into one Request, which delivers all data with a single Request.
(~300kb data)
Make a startup page, with low amount of requests and data.
(~50kb data)
Better idea?
I prefer, that i can keep the current startup page. Can you share your experiance?
You have pointed out the two main ways to reduce the start-up time.
1.- Reduce requests: With RF you can group all requests in one if you share the same service instance and call only once the .fire() method. Use Bundles for images, css, and other resources so as them are downloaded in the same request.
2.- Reduce the js size: split your code in pieces using GWT.runAsync(). So the first piece of code could be the minimum stuff for starting your app until the user interacts with it. You can use the gwt compilation reports to see whether your code is bigger. You can use the new closure compiler in gwt-2.5 to reduce and optimize the final js.
3.- Another thing you must check is that your webserver configuration is sending the appropriate headers so as the browser caches gwt fragments, as well as you should check if it is compressing the files before sending to the client. You can make gwt compiler to pre-compress those js fragments though.
4.- For successive loads, I mean the user goes to your app a second time, consider using localstorage for caching certain things which don't change instead of requesting them again. Configure your HTML5Manifest, if you are using mgwt, it is really easy since they include a linker to produce the manifest in compile time.
5.- Consider using light-weight widgets and frameworks instead of heavy widgets (js collections, elemental, gquery, mgwt, etc).
I have several recommendation:
Load data that changed rarely in a single request at start up.
Activate GZip compression on your server.
Use background call when application start up finished in user idle time.
Group related request in a single request.

Android File Upload Queue with Cancellation support

We are developing an Android application, where there is a need to upload several photos to our server in an asynchronous way. Consider that as soon as a picture is taken, it will start being uploaded. As soon as it has finished being uploaded, the next one (all of them will be placed in a queue) will start being uploaded.
However, it is also important to support cancellation functionality, meaning that the user can interact with the app in a way that will remove an image from the queue or even cancel a running upload.
After searching for possible solutions, we have come to the following possible scenarios:
1) Use an IntentService for the queue mechanism and implement our own logic inside it. However, there are some worries as to how easy it is going to be to support cancellation.
2) Use the SD card and a local database to store the files and a Service to check for new files. This has been described here:
Android (or iOS) - Image Upload Queue
3) Find a way to use the built-in Android DownloadManager for uploads (can it really be done?)
4) Use AsyncTask and isCancelled() function.
5) Or ideally find another built-in Android/Java mechanism to do all of the above in a seamless way.
Any ideas?

Categories

Resources