-
Notifications
You must be signed in to change notification settings - Fork 17
/
Apache Cordova Document;Note=Erxin.txt
2974 lines (2329 loc) · 103 KB
/
Apache Cordova Document;Note=Erxin.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Apache Cordova Document;Note=Erxin
# Introduction
- mobile development framework, allows use standard web technologies
- architecture
Web App
A
|html api & cordova api
V
Html Rendering Engine(WebView) <-cordova native api-> Cordova Plugins
A A
|os apis |
V |
mobile os <-----------------------------------------------------------------------+
- webview, cordova-enbaled webview may provide the application with its entire user interface
- web app run in webview within naive wrapper. the contain has a config.xml file for specify such as orientation shifts
- plugins provides an interface for cordova and native components to communicate with each other and bindings to standard device APIs
there a list of core plugins http://cordova.apache.org/docs/en/latest/guide/support/index.html#core-plugin-apis
cordova CLI
Embedded WebView
Plugin Interface
Accelermeter
BatteryStatus
Camera
Capture
Compass
Connection
Contacts
Device
Events
File
File Transfer
Geolocation
Globalization
InAppBrowser
Media
Notification
SplashScreen
StatusBar
Storage
Vibration
search for plugins by plugin search or npm
check more detail for plugin development guide http://cordova.apache.org/docs/en/latest/guide/hybrid/plugins/index.html
plugin must be explicit added
- development path
+ cross-platform CLI workflow, want run as many os as possible. demo for create your first app http://cordova.apache.org/docs/en/latest/guide/cli/index.html. the CLI is a high-level tool
+ platform centered this discussed in Embedded webviews http://cordova.apache.org/docs/en/latest/guide/hybrid/webviews/index.html. this will relies on a set of low level shell scripts
there is a on direction switch from CLI to platform center.
# Create your first Cordova app
- user cordova command-line
- installing the cordova CLI
$ npm install -g cordova
- create an app
$ cordova create hello com.example.hello HelloWorld
this will create a skeletal web-based application
- add platforms
$ cd hello
add platforms that you wantted
$ cordova platform add ios --save
$ cordova platform add android --save
check current installed platforms
$ cordova platforms ls
- install pre-requisites for building. required sdk for each platform, if using browser for development can use browser paltform which does not require any platform sdks
+ check satisfay requirements for build
$ cordova requirements
- build the app
+ start page is
www/index.html
+ any intialization should be specified as part of the deviceready event handler in www/js/index.js
+ build all platfroms
$ cordova build
+ build specify platform
$ cordova build ios
+ CLI reference http://cordova.apache.org/docs/en/latest/reference/cordova-cli/index.html#cordova-build-command
- test app
+ execute in android emulator
$ cordova emulate andriod
+ execute in the real hardware
$ cordova run android
reference setup android emulator http://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html#setting-up-an-emulator
- add plugins
+ use plugin search page
http://cordova.apache.org/plugins/
+ use command line to open search page
$ cordova plugin search camera
+ plugins can also be added using a directory or a git repo check the CLR command reference
+ use plugman to mange plugins, http://cordova.apache.org/docs/en/latest/plugin_ref/plugman.html
+ check current installed plugin, plugin ls or plugin list, or plugin
$ cordova plugin ls
- use merges to customize each platform
+ modify source files in various www directories within the top-level platforms directory, they're regularly replaced with the top-level www directory cross-platform source
+ top-level merges directory offers a place to specify asses to deploy on specific platforms, each platform-specific subdirectory within merges
+ use merges mirrors the directory structure of www source tree, allowing you to override or add files as needed
+ example
* add override.css to www/index.html
<link rel="stylesheet" type="text/css" href="css/override.css"/>
* optionally add an empty www/css/override.css file, which will be apply for all non-android builds
* create a css subdirectory within merges/android, then add a corresponding override.css
* when rebuild the project the android build will use the customized override.css
- updating cordova and your project
+ update cordova utility to latest version
$ npm update -g cordova
+ install specific version
$ npm install -g [email protected]
+ check current installed version
$ npm info cordova version
+ update trageting platform
$ cordova platform update android --save
# Platform Support
- a set of development tools and device APIs
reference http://cordova.apache.org/docs/en/latest/guide/support/index.html
# Android Platform Guides
- requirements and support
+ latest android package supports up to android API-level 23
5.x.x 14-23
4.1.x 14-22
4.0.x 10-22
3.7.x 10-21
+ a general rule, andriod version become unsupported by cordova as they dip below 5% on google's distribution dashboard
- adding sdk packages
+ suggest install the latest version for cordova which supported
+ open android sdk manager make sure
* android platform sdk
* android build tool version 19.1.0 or higher
* android support repository (under extras)
- setting environment variables
+ set JAVA_HOME
+ set ANDROID_HOME
+ add android sdk tool and platform-tools to path
- OSX and linux
+ use a text editor to create or modify the ~/.bash_profile, add line
export ANDOID_HOME=/Development/android-sdk/
+ update your path, add a line resembling the following(substitue the paths with your local android sdk installation's location)
export PATH=${PATH}:/Development/android-sdk/platform-tools:/Development/android-sdk/tools
reload your terminal to see changes by
$ source ~/.bash_profile
- project configuration
+ setting up an emulator
create a android virtual device (avd).
after that run cordova cli to check the device
$ cordova run --list
- adding sdk packages
+ install the packages for whatever API level (http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels)
+ open android sdk manager
* install sdk
* install build tools version 19+
* android support reporsitory(under extras)
- setting environment variables
JAVA_HOME to JDK install location
ANDROID_HOME, to android sdk installation location
add android sdk tools and platform-tools directories to your PATH
http://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html
- setting up an emulator
+ create an android virtual device(AVD) http://developer.android.com/tools/devices/managing-avds.html
check current avaliable devices
$ cordova run --list
- configuring gradle
+ [email protected] are built using Gradle(http://gradle.org/)
Gradle is a open source polyglot build automation system Automate and integrate your DevOps toolchain with a concise and expressive build programming language
+ setting gradle properties https://docs.gradle.org/current/userguide/build_environment.html
cdvBuildMultipleApks, if set multiple APK files are generated supported by library projects(x86, ARM, etc). If not set a single APK will be generated
cdvVersionCode, override the versionCode set in the AndroidManifest.xml
cdvReleaseSigningPropertiesFile, path to a .properties file that contains signing information
cdvDebugSigningPropertiesFile, signing information for debug builds
cdvMinSdkVersion, overrides the value of minSdkVersion set in AndroidManifest.xml
cdvBuildToolsVersion, override the android.buildToolVersion value
cdvCompileSdkVersion, override the automatically detected android.compileSdkVersion
+ support set properties in one of four ways
* environment variables
$ export ORG_GRADLE_PROJECT_cdvMinSdkVersion=20
$ cordova build android
* by using the --gradleArg flag in your Cordova build or run commands
$ crodova run android -- --gradleArg=-PcdvMinSdkVersion=20
* by palcing a file called gradle.properties in your android platform folder <project>/platforms/android/gradle.properties
#comments line
cdvMinSdkVersion=20
* by extending build.gradle via a build-extras.gradle file and setting the property like so
// In <your-project>/platforms/android/build-extras.gradle
ext.cdvMinSdkVersion = 20
the files required by the last two options could be copied by before_build hook
- extending build.gradle
+ customize build.gradle
create a sibling file named build-extras.gradle, it will be included by the main build.gradle when present. it must be placed at // In <your-project>/platforms/android/ folder
recommended copy and replaced it with before_build hook (http://cordova.apache.org/docs/en/latest/guide/appdev/hooks/index.html)
* example
// Example build-extras.gradle
// This file is included at the beginning of `build.gradle`
ext.cdvDebugSigningPropertiesFile = '../../android-debug-keys.properties'
// When set, this function allows code to run at the end of `build.gradle`
ext.postBuildExtras = {
android.buildTypes.debug.applicationIdSuffix = '.debug'
}
+ plugins can also include build-extras.gradle files via
<framework src="some.gradle" custom="true" type="gradleReference" />
- setting the version code. change version code for generated apk. set the android-versionCode attribute in the widget element of your application's config.xml file. If the android-versionCode is not set, the version code will be determined using the version attribute
versionCode = MAJOR * 10000 + MINOR * 100 + PATCH
+ if your application has enabled the cdvBuildMultipleApks. gradle property the version code will also be multiplied by 10. the latest code can be used to indicate the architecture apk
+ increase the android-versionCode property based on the value in your config.xml file's android-versionCode
- signing an App, need follow parameters
Keystore, --keystore, path to a binary file hold a set of keys
Keystore Password, --storePassword
Alias, --alias, the id specifing the private key used for singing
password, --password, password for the private key
type of the keystore, --keystoreType, auto-detected based on file etension either pkcs12 or jks
thexe parameters could be specified by CLI build/run commands
+ use -- to indicate these are platform-sepcific arguments
$ cordova run android --release -- --keystore../my-release-key.keystore --storePassword=password --alias=alias_name --password=password
- using build.json, using the --buildConfig argument to the same command
+ example
{
"android": {
"debug": {
"keystore": "../android.keystore",
"storePassword": "android",
"alias": "mykey1",
"password" : "password",
"keystoreType": ""
},
"release": {
"keystore": "../android.keystore",
"storePassword": "",
"alias": "mykey2",
"password" : "password",
"keystoreType": ""
}
}
}
- using gradle, specify signing properties by .properties file and pointing to it with the cdvReleaseSigningPropertiesFile and cdvDebugSigningPropertiesFile Gradle properties
+ contents
storeFile=relative/path/to/keystore.p12
storePassword=SECRET1
storeType=pkcs12
keyAlias=DebugSigningKey
keyPassword=SECRET2
+ reference http://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html#setting-gradle-properties
- debugging
+ check android sdk developer document for debugging
+ open a project in android studio. when opening your project in android studio recommended you do not edit your code in the IDE. this will edit the code in the platforms folder(not www) and changes are liable to be overwritten instead, edit the www folder and then run $ cordova build
+ plugin developer wishing to edit their native code in the IDE should use --link flag when adding their plugin to the project via $ cordova plugin add. the changes will sync between the platforms folder and the plugin's source folder
+ example open cordova project
* launch android studio
* select import project(Eclipse ADT, gradle, etc)
* select the android platform directory in <your-project>/platforms/android
* for the gradle sync question click Yes
* run the application directly in the android studio
http://developer.android.com/tools/building/building-studio.html
http://developer.android.com/tools/studio/index.html
- platform centered workflow
+ cordova-android includes a number of scripts that allow the platform to be usd without full Cordova cli
+ each of the scripts discussed below refer to cordova CLI reference, for example cordova-android/bin/create equivalent to $ cordova create
+ install plugin with Plugman utility
- upgrating, upgrade from older version android project, reference http://cordova.apache.org/docs/en/latest/guide/platforms/android/upgrade.html
- lifecycle guide
+ cordova and android
native android apps typically consist of a series of activities. each activity has its own lifecycle
+ in constrast cordova applications on android are executed in a webview which embedded in a single android activity. the lifecycle of this activity is exposed to your application through document events that are fired. the events are not guaranteed to line up with android's lifecycle.
cordova-event android-event
deviceready onCreate()
pause onPause()
resume onResume()
+ android activity may be removed due to lower memory, so when return back cordova app may lost data so make sure save the user state whenever user leave the application
+ when can this happen
* user press home button or switches to another application
* certain plugins can introduce, such as camera
* clearer understanding the second case
everything goes as planned the workflow will be
1. user is interacting with your app, need user take a photo
2. camera plugin lauches, cordova app is pushed back
3. user take a photo
4. camera activity finished, cordova activity is moved to the foreground
5. user returned to your application
this flow can be disrpted if a device is low on memory
1. user interacting with your app, need take a photo
2. camera plugin launch, os destroy the cordova activity (pause event is fired)
3. user take a photo
4. camera activity finished, os recreates the cordova activity(deviceready and resume events are fired)
5. user confused why they are back to login screen
* to overcome this we need subscribing to events and property maintaining state as part of the activity lifecycle
+ respecting the lifecycle
when the cordova plugin destroied from cordova-android 5.1.0 provide a means for getting the native callback when application resume
resume event's payload will contain any pending plugin results from the plugin request that lauched the external activity made prior to the activity being destroyed. formats
{
action: "resume",
pendingResult: {
pluginServiceName: string, //name of the plugin
pluginStatus: string, //status of the plugin
result: any //whatever the result of the plugin call
}
}
pluginStatus: OK, NoResult, Error other miscellaneous errors "Class not found" "Illegal access" "Instantiation error", "Malformed url", "IO error", "JSON error"
+ example for handling camera resume plugin
// This state represents the state of our application and will be saved and
// restored by onResume() and onPause()
var appState = {
takingPicture: true,
imageUri: ""
};
var APP_STORAGE_KEY = "exampleAppState";
var app = {
initialize: function() {
this.bindEvents();
},
bindEvents: function() {
// Here we register our callbacks for the lifecycle events we care about
document.addEventListener('deviceready', this.onDeviceReady, false);
document.addEventListener('pause', this.onPause, false);
document.addEventListener('resume', this.onResume, false);
},
onDeviceReady: function() {
document.getElementById("take-picture-button").addEventListener("click", function() {
// Because the camera plugin method launches an external Activity,
// there is a chance that our application will be killed before the
// success or failure callbacks are called. See onPause() and
// onResume() where we save and restore our state to handle this case
appState.takingPicture = true;
navigator.camera.getPicture(cameraSuccessCallback, cameraFailureCallback,
{
sourceType: Camera.PictureSourceType.CAMERA,
destinationType: Camera.DestinationType.FILE_URI,
targetWidth: 250,
targetHeight: 250
}
);
});
},
onPause: function() {
// Here, we check to see if we are in the middle of taking a picture. If
// so, we want to save our state so that we can properly retrieve the
// plugin result in onResume(). We also save if we have already fetched
// an image URI
if(appState.takingPicture || appState.imageUri) {
window.localStorage.setItem(APP_STORAGE_KEY, JSON.stringify(appState));
}
},
onResume: function(event) {
// Here we check for stored state and restore it if necessary. In your
// application, it's up to you to keep track of where any pending plugin
// results are coming from (i.e. what part of your code made the call)
// and what arguments you provided to the plugin if relevant
var storedState = window.localStorage.getItem(APP_STORAGE_KEY);
if(storedState) {
appState = JSON.parse(storedState);
}
// Check to see if we need to restore an image we took
if(!appState.takingPicture && appState.imageUri) {
document.getElementById("get-picture-result").src = appState.imageUri;
}
// Now we can check if there is a plugin result in the event object.
// This requires cordova-android 5.1.0+
else if(appState.takingPicture && event.pendingResult) {
// Figure out whether or not the plugin call was successful and call
// the relevant callback. For the camera plugin, "OK" means a
// successful result and all other statuses mean error
if(event.pendingResult.pluginStatus === "OK") {
// The camera plugin places the same result in the resume object
// as it passes to the success callback passed to getPicture(),
// thus we can pass it to the same callback. Other plugins may
// return something else. Consult the documentation for
// whatever plugin you are using to learn how to interpret the
// result field
cameraSuccessCallback(event.pendingResult.result);
} else {
cameraFailureCallback(event.pendingResult.result);
}
}
}
}
// Here are the callbacks we pass to getPicture()
function cameraSuccessCallback(imageUri) {
appState.takingPicture = false;
appState.imageUri = imageUri;
document.getElementById("get-picture-result").src = imageUri;
}
function cameraFailureCallback(error) {
appState.takingPicture = false;
console.log(error);
}
app.initialize();
//corresponding html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Cordova Android Lifecycle Example</title>
</head>
<body>
<div class="app">
<div>
<img id="get-picture-result" />
</div>
<Button id="take-picture-button">Take Picture</button>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
+ android provides a developer setting for testing activity destruction on low memory. Enable "Don't keep activities" setting in the develop options
# Blackberry 10
# iOS
# OS X
# Ubuntu
# Windows
# WP8
# Manage versions and platforms
- support save and restore platforms and plugins. save store information in config.xml. restore step happens automatically when a cordova prepare is issued
this make a large team development easier
- platform versioning
$ cordova platform add <platform[@<version>] | directory | git_url> --save
+ this command add content to cofig.xml
<?xml version='1.0' encoding='utf-8'?>
...
<engine name="android" spec="~4.0.0" />
...
</xml>
- mass saving platforms on an exiting project
$ cordova platform save
- updating/removing platforms
$ cordova platform update <platform[@<version>] | directory | git_url> --save
$ cordova platform remove <platform> --save
- restoring platforms. by command $ cordova prepare. if you add a platform without specifying a version then it will taken from the config.xml if found
- plugin versioning
$ cordova plugin add <plugin[@<version>] | directory | git_url> --save
- save all plugin information
$ cordova plugin save
- remove plugin information
$ cordova plugin update <plugin[@<version>] | directory | git_url> --save
$ cordova plugin remove <plugin> --save
- restoring rule is same as platform, config.xml is used first
# Customize Icons
- SplashScreen plugin document for how to configuration an app's icon for various platforms
http://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/
- configuring icons in the CLI
+ define app icons via <icon> element in config.xml. if not the cordova icon is used
<icon src="res/ios/icon.png" platform="ios" width="57" height="57" density="mdpi" target="filename and all its MRT companions"/>
src, is required other properties are all optional
density, is for andoird
target is for windows
+ define a pixel-perfect icons set to fit different screen resolutions
<platform name="android">
<!--
ldpi : 36x36 px
mdpi : 48x48 px
hdpi : 72x72 px
xhdpi : 96x96 px
xxhdpi : 144x144 px
xxxhdpi : 192x192 px
-->
<icon src="res/android/ldpi.png" density="ldpi" />
<icon src="res/android/mdpi.png" density="mdpi" />
<icon src="res/android/hdpi.png" density="hdpi" />
<icon src="res/android/xhdpi.png" density="xhdpi" />
<icon src="res/android/xxhdpi.png" density="xxhdpi" />
<icon src="res/android/xxxhdpi.png" density="xxxhdpi" />
</platform>
- ios
<platform name="ios">
<!-- iOS 8.0+ -->
<!-- iPhone 6 Plus -->
<icon src="res/ios/[email protected]" width="180" height="180" />
<!-- iOS 7.0+ -->
<!-- iPhone / iPod Touch -->
<icon src="res/ios/icon-60.png" width="60" height="60" />
<icon src="res/ios/[email protected]" width="120" height="120" />
<!-- iPad -->
<icon src="res/ios/icon-76.png" width="76" height="76" />
<icon src="res/ios/[email protected]" width="152" height="152" />
<!-- iOS 6.1 -->
<!-- Spotlight Icon -->
<icon src="res/ios/icon-40.png" width="40" height="40" />
<icon src="res/ios/[email protected]" width="80" height="80" />
<!-- iPhone / iPod Touch -->
<icon src="res/ios/icon.png" width="57" height="57" />
<icon src="res/ios/[email protected]" width="114" height="114" />
<!-- iPad -->
<icon src="res/ios/icon-72.png" width="72" height="72" />
<icon src="res/ios/[email protected]" width="144" height="144" />
<!-- iPhone Spotlight and Settings Icon -->
<icon src="res/ios/icon-small.png" width="29" height="29" />
<icon src="res/ios/[email protected]" width="58" height="58" />
<!-- iPad Spotlight and Settings Icon -->
<icon src="res/ios/icon-50.png" width="50" height="50" />
<icon src="res/ios/[email protected]" width="100" height="100" />
</platform>
- windows recommend approach is used target attribute
<platform name="windows">
<icon src="res/windows/storelogo.png" target="StoreLogo" />
<icon src="res/windows/smalllogo.png" target="Square30x30Logo" />
<icon src="res/Windows/Square44x44Logo.png" target="Square44x44Logo" />
<icon src="res/Windows/Square70x70Logo.png" target="Square70x70Logo" />
<icon src="res/Windows/Square71x71Logo.png" target="Square71x71Logo" />
<icon src="res/Windows/Square150x150Logo.png" target="Square150x150Logo" />
<icon src="res/Windows/Square310x310Logo.png" target="Square310x310Logo" />
<icon src="res/Windows/Wide310x150Logo.png" target="Wide310x150Logo" />
</platform>
- windows phone 8
<platform name="wp8">
<icon src="res/wp/ApplicationIcon.png" width="99" height="99" />
<!-- tile image -->
<icon src="res/wp/Background.png" width="159" height="159" />
</platform>
# Storage
- html5 approach
- localStorage
window.localStorage
- websql
android
blackBerry 10
iOS
- indexedDB
android
blackBerry 10
windows limitation
+ not avaliable in web workers
+ not support array keys
+ doesn't support object lookup via compound index
android 4.4+
- plugin based options
+ FileSystem api in chrome. File plugin provides an extensive implementation and support in all platforms
+ Sqlite plugin
cordova-sqlite-storage - core version that relies on native SQLite implementation. As such, it is only available for iOS and Android platforms.
cordova-sqlite-ext - extended version with additional features including support for Windows and REGEXP support on Android and iOS.
cordova-sqlite-evfree - similar to cordova-sqlite-ext but with improved memory handling. Available under GPL v3 or commercial license.
# Manage Privacy
- privacy guide
+ privacy policy
make your privacy policy available for users to review prior to download
+ collection of sensitive information, such as geolocation, contacts/phonebook, microphone/camera, stored pictures/videos
+ avoiding user surprise
+ thrid party data collection or sharing should be inform
+ collection limitation and security
# Manage security
- whitelist
+ read the whitelist guide http://cordova.apache.org/docs/en/latest/guide/appdev/whitelist/index.html
+ domain whitelist doesn't work on android API 10- and wp8 for iframes and xmlhttprequest
+ use inAppBrowser plugin or other third-party plugins
- iframes and the callback id mechanism
+ content is served in an iframe from a whitelisted domain, taht domain will have access to the natie cordova bridge. this means that if your whitelist third-party advertising network these ads possible be a malicious ad will be able to break out the iframe
+ there are thrid party plugins to support advertising network. this statement is not ture for iOS, which intercept everyting including iframe connections
- certificate pinning
+ cordova doesnot support true certificate pinning. the main barrier is a lack of native APIs in android for intercepting SSL connection to perform the check of the server's certificate
+ there are ways to approximate certificate pinning sch as checking server's public key(fingerprint) while your app starts or other various times.
+ there are also plugins that do true certificate pinning for some platforms
- self signed certificates for your server is not recommend. it should be signed by a well-known CA.
The reason is that accepting self-signed certificates bypasses the certificate chain validation, which allows any server certificate to be considered valid by the device. This opens up the communication to man-in-the-middle attacks.
When running Cordova on Android, using android:debuggable="true" in the application manifest will permit SSL errors such as certificate chain validation errors on self-signed certs.
- general tips
+ do not user android Gingerbread, it is API 10
+ use inAppBrowser for outside links
+ validate all user input
+ do not cache sensitive data
+ don't use eval() unless you know what you're doing
+ do not assume that your source code is secure
- reference
https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet
https://github.com/phonegap/phonegap/wiki/Platform-Security
http://www.cis.syr.edu/~wedu/Research/paper/webview_acsac2011.pdf
# Whitelist Guide
- cordova provide a policy to configure which external sites may be accessed
- android 4.0+ should use cordova-plugin-whitelist plugin
- add <access> element within the app's config.xml file
+ access to google.com, support wildcard match, origin="*" means all
<access origin="http://google.com" />
- cordova-iso version 4.0+ does not require the cordova-plugin-whitelist to be installed
<allow-intent> and <allow-navigation>
- windows phone whitelist are found in the config.xml file
# Create plugins
- plugin comprise as a single javascript interface along with corresponding native code libraries for each supported platform
- building a plugin
+ using CLI's plugin add command to add a plugin to a project. add from git repo
$ cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-device.git
+ plugin repo must feature a top-level plugin.xml manifest file
//example
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
id="cordova-plugin-device" version="0.2.3">
<name>Device</name>
<description>Cordova Device Plugin</description>
<license>Apache 2.0</license>
<keywords>cordova,device</keywords>
<js-module src="www/device.js" name="device">
<clobbers target="device" />
</js-module>
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="Device">
<param name="ios-package" value="CDVDevice"/>
</feature>
</config-file>
<header-file src="src/ios/CDVDevice.h" />
<source-file src="src/ios/CDVDevice.m" />
</platform>
</plugin>
reference http://cordova.apache.org/docs/en/latest/plugin_ref/spec.html
- validating a plugin using plugman utility
$ npm insall -g plugman
+ need a valid app source directory
+ example avlid iOS dependencies load properly
$ plugman install --platform ios --project /path/to/my/project/www --plugin /path/to/my/plugin
+ plugman reference, http://cordova.apache.org/docs/en/latest/plugin_ref/plugman.html
- the javascript interface
+ structure your plugin's javascript, you need to call cordova.exec to communicate with the native platform using following syntax
cordova.exec(function(winParam) {},
function(error) {},
"service",
"action",
["firstArgument", "secondArgument", 42, false]);
function(winParam), a success callback function, assuming your exec call complete successfully
"service", the service name to call on the native side, corresponds to a native class
"action", action name on the native side
"[]", arrary of arguments
- sameple javascript
window.echo = function(str, callback) {
cordova.exec(callback, function(err) {
callback('Nothing to echo.');
}, "Echo", "echo", [str]);
};
//use the plugin
window.echo("echome", function(echoValue) {
alert(echoValue == "echome"); // should alert true.
});
- native interface should be implement separately for each platform
+ android
+ iOS
+ blackBerry
+ window phone 8
+ window
- publishing plugins publish your plugin to any npmjs-based registry recommand use https://www.npmjs.com/ then other developer could use your plugin automatically by plugman or Cordova CLI
+ isntall plugman
$ npm install -g plugman
+ create package.json
$ plugman createpackagejson path-to-your-plugin
+ publish
$ npm add user # that is if you dont have an account yet
$ npm publish path-to-your-plugin
reference publish a npm package https://docs.npmjs.com/getting-started/publishing-npm-packages
- integrating with plugin search
+ add ecosystem:cordova keyword to package.json to surface your plugin in Cordova Plugin Search
+ indicate support for a particular platform add a keword with <paltformName> as **cordova-<platformName>** to the list of keywords in pacakge.json
//example for a plugin that support android, ios and windows
"keywords": [
"ecosystem:cordova",
"cordova-android",
"cordova-ios",
"cordova-windows"
]
for a detail example check the https://github.com/apache/cordova-plugin-device/blob/master/package.json
- specifying cordova dependencies
cordova 6.1.0 added support for specifying the related dependencies of a plugin as part of pacakge.json. get more detail from plugin.xml(http://cordova.apache.org/docs/en/latest/plugin_ref/spec.html#engines-and-engine)
+ specify cordova-related dependencies to package.json
engines: {
cordovaDependencies: {
PLUGIN_VERSION: {
DEPENDENCY: SEMVER_RANGE,
DEPENDENCY: SEMVER_RANGE,
...
},
...
}
}
PLUGIN_VERSION, specify a version of your plugin, it should adhere the syntax for a single version as defined by npm's semver pakcage or an upper bound https://www.npmjs.com/package/semver
DEPENDENCY may be one of the following
+ the cordova CLI "cordova"
+ a cordova platform (e.g "cordova-android", "cordova-ios", "cordova-windows", etc )
+ andother cordova plugin (e.g "cordova-plugin-camera", etc )
SEMVER_RANGE, should adhere to the synatx for a range as define in nmp's semver https://www.npmjs.com/package/semver
cordovaDependencies may list any number of PLUGIN_VERSION requirements and any number of DEPENDENCY. version of your plugin that do not have their dependencies listed will be assumed to have the same dependency information as the highest PLUGIN_VERSION listed below them
engines: {
cordovaDependencies: {
"1.0.0": { "cordova-android": "<3.0.0"},
"2.1.0": { "cordova-android": ">4.0.0"}
}
}
below 1.0.0 is assumed have no dependencies, version between v1.0.0 and 2.1.0 are same.
- upper bounds, a single versio a PLUGIN_VERSION in cordovaDependencies may also specify an upper bound to amend entries for older release of your plugin
engines: {
cordovaDependencies: {
"0.0.1": { "cordova-ios": ">1.0.0" },
"<1.0.0": { "cordova-ios": "<2.0.0" },
"<2.0.0": { "cordova-ios": "<5.0.0" }
}
}
PLUGIN_VERSION allowed single versions or uppper bounds, no other semver ranges are supported
the rule will be combined to "cordova-ios >1.0.0 AND cordova-ios <2.0.0 AND cordova-ios <5.0.0"
# Develop plugin for Android
- android plugins are based on cordova-android, which is built from an android webview with a native bridge. the native portion of an android plugin consists of at least one java class that extend the CordovaPlugin class and overrides one of its execute methods
+ example project
https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java
- plugin class mapping
+ plugin's javascript interface uses the cordova.exec method as follows
exec(<successFunction>, <failFunction>, <service>, <actions>, [<args>]);
this marshals a request from the webview to the android native side
whether you distribute a plugin as java file or as a jar file of its own, the plugin must be specified in your cordova-android application's res/xml/config.xml
use plugin.xml file to inject this feature
<feature name="<service_name>">
<param name="android-package" value="<full_name_including_namespace>"/>
</feature>
the service name matchs the one used in the JavaScript exec call. the value is the java class's full qulified namespace identifier
- plugin initialization and lifetime
+ one instance of a plugin object is created for the life of each webview. plugins are not instantiated until they referenced by a call from javascript unless <param> with a onlaod name attribute is set to "true"
<feature name="Echo">
<param name="android-package" value="<full_name_including_namespace>" />
<param name="onload" value="true" />
</feature>
+ plugins should use the initialize method for their start-up logic
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
// your init code here
}
+ plugins have access to android lifecycle events
- writing an android java plugin
+ a javascript call fires off a plugin request to the native side. and the corresponding java plugin is mapped properly in the config.xml file
+ the execute method of plugin class look like this
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if ("beep".equals(action)) {
this.beep(args.getLong(0));
callbackContext.success();
return true;
}
return false; // Returning false results in a "MethodNotFound" error.
}
- threading, plugin's javascript does not run in the main thread of webview. instead it runs on the webcore thread
+ to interactive with UI thread, you should use the activity's runOnUiThread
@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
if ("beep".equals(action)) {
final long duration = args.getLong(0);
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
...
callbackContext.success(); // Thread-safe.
}
});
return true;
}
return false;
}
+ if you do not need to run on the UI thread, but do not wish to block the webcore thread either, you should execute your code using the cordova ExecutorService obtained with cordova.getThreadPool()
@Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
if ("beep".equals(action)) {
final long duration = args.getLong(0);
cordova.getThreadPool().execute(new Runnable() {
public void run() {
...
callbackContext.success(); // Thread-safe.
}
});
return true;
}
return false;
}
- adding dependency libraries, they must be listed in the plugin.xml in one of two ways
+ use <framework/> tag. specify the libraries in the manner allows them to be resolved via gradle's dependency management logic
+ use <lib-file/> tag to specify the location of a jar file. this should only be used if you are sure that no other plugin will be depending on the library you are referencing(if the library is specific to your plugin). other wise the user may encounter native build error if other plugins also reference the same library
- echo android plugin example, to match the javascript interface's each feature use plugin.xml to inject a feature to the local platform's config.xml file
<platform name="android">
<config-file target="config.xml" parent="/*">
<feature name="Echo">
<param name="android-package" value="org.apache.cordova.plugin.Echo"/>
</feature>
</config-file>
<source-file src="src/android/Echo.java" target-dir="src/org/apache/cordova/plugin" />
</platform>
+ add following code to the src/android/Echo.java file
package org.apache.cordova.plugin;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* This class echoes a string called from JavaScript.
*/
public class Echo extends CordovaPlugin {
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("echo")) {
String message = args.getString(0);
this.echo(message, callbackContext);
return true;
}
return false;
}