While starting a new Cordova app is quite an easy process, I was a bit surprised by the difficulty to properly embed a Cordova webview into a native app. Resources on the web on this subject are not particularly easy to find and most of the time outdated. Here is a few links and explanations that should make your life easier in case you're going to embed Cordova 5+!
How does it works?
When embedding a Cordova webview, the process is to:
- Create a Cordova project in a folder, and add the platform(s) you need.
- Import the Cordova lib in your iOS or Android app
- Import/symlink the
www
folder of your Cordova app1 and the Cordova plugins code, both fromplatforms/<your os>
. - Import/symlink the
config.xml
located inplatforms/<your os>
. - Create the Cordova webview inside your iOS or Android app.
In any case, your starting point should be the Cordova documentation.
At any time, to check that Cordova is properly embedded, you can take a look at the logs of your app to see if Cordova plugins are initialized.
For instance, the device plugin is installed by default on all Cordova projets. In a JS debugger, type device
and if you don't see any null values, then your plugins are working.
Remember to call cordova prepare
Anytime you make changes to your JS app, the changes must be applied too in the native app. This is what cordova prepare
is doing. The prepare step is also launched if you run cordova build
or cordova run
. If you've done only change in the JS part of the app, make sure to call cordova prepare
before relaunching your app with XCode or Android Studio.
How to communicate between Javascript and the native part?
Cordova is already implementing a bridge between Javascript and the native app thanks to plugin mechanism.
Android
On Android, if you want to call native methods you have two solutions:
- You can roll your own plugin
- Or you can use
JavascriptInterface
. It's super easy and super quick to use without having to make your own plugin. See the Google documentation about it: https://developer.android.com/guide/webapps/webview.html
iOS
For iOS, it's harder to expose methods without making your own plugin. You can try to override the Cordova delegate for the webview and then redefine webView:shouldStartLoadWithRequest:navigationType:
but you are likely to break Cordova things (like plugins loading or navigation) and lose a lot of time figuring this. Making your own Cordova plugin seems the best way to do things properly.
For calling Javascript from your native iOS app, stringByEvaluatingJavaScriptFromString:
is the way to go.
See the documentation for UIWebView here and there
Android specificities
A more detailed step-by-step guide
Read this excellent blog article about embedding Cordova on Android.
You'll see how to include the Cordova jar (that's the step (2) of the list), make
symlinks to the www
folder and plugins Java folders (step (3)), make a symlink to the config.xml
from platforms/android
(step (4)).
Cordova/the webview is not working when building for release
If your native Android app is using Proguard to minify/obfuscate the app, make sure you add exceptions. Otherwise, Proguard will strip the code related to the webview and in particular the JavascriptInterface
methods you've declared!
See this Stack Overflow thread to exclude Cordova and related classes from Proguard stripping.
Startup performance
The webview is quickly loaded on iOS (a few milliseconds) but it's longer on Android. My solution was to create a loader in the native Android app, displayed below the Cordova webview.
If the JS framework that you're using to building your app is a bit long to load too, you may want to replicate this loader using raw CSS so that the user can see the loader while the framework is bootstrapping.
-
You must not symlink the original www folder but the one in platforms/iosor platforms/android. This is because Cordova applies some magic on the files in platforms/. ↩