Compare commits
2417 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7572fc4912 | ||
|
|
9286496378 | ||
|
|
9d3d8d0521 | ||
|
|
636136c88e | ||
|
|
bedb4427f4 | ||
|
|
35f0d07521 | ||
|
|
b94409ffe0 | ||
|
|
adc380cf9f | ||
|
|
7da531ced5 | ||
|
|
3e870e3a04 | ||
|
|
f15fec81cf | ||
|
|
53d60dd707 | ||
|
|
68a302e9d2 | ||
|
|
16ff6e1b2f | ||
|
|
f6d1deeff6 | ||
|
|
1f0ea173b0 | ||
|
|
70a1eff705 | ||
|
|
fb36e03aeb | ||
|
|
8a9cb8f6b7 | ||
|
|
b31e024dbb | ||
|
|
422ce4f6bf | ||
|
|
b8d32d7c60 | ||
|
|
83b3998801 | ||
|
|
180a1a39f0 | ||
|
|
a1ed525a0b | ||
|
|
2037b62f99 | ||
|
|
21f64806c0 | ||
|
|
e8cbeaaa1b | ||
|
|
facffb0809 | ||
|
|
6f35d0b2b7 | ||
|
|
334d02d26e | ||
|
|
69b24dbf6a | ||
|
|
510596f515 | ||
|
|
47aa116b1d | ||
|
|
015db819ae | ||
|
|
01569ce71a | ||
|
|
0f13f4a5ac | ||
|
|
6d803e2f72 | ||
|
|
ae4dba2bb8 | ||
|
|
a45804329b | ||
|
|
1b7874607e | ||
|
|
ff1ae2125a | ||
|
|
f9e8ce8fab | ||
|
|
5e7be8e1d6 | ||
|
|
b2d9d639b4 | ||
|
|
8d407708d4 | ||
|
|
19bbf1e8c1 | ||
|
|
2a84d7c44d | ||
|
|
eeb645c886 | ||
|
|
676f98d82d | ||
|
|
9c3195c1ee | ||
|
|
2a92c77772 | ||
|
|
eefa91b3ea | ||
|
|
6b33772613 | ||
|
|
cab9840a03 | ||
|
|
63b2356575 | ||
|
|
a9ee9196bd | ||
|
|
6588994586 | ||
|
|
46d4d924cc | ||
|
|
dc8854d16c | ||
|
|
a33044921d | ||
|
|
9c165cb94f | ||
|
|
e0d5d14895 | ||
|
|
35bc354531 | ||
|
|
ac4d3d1d45 | ||
|
|
be9abf5f91 | ||
|
|
c04ea9b1c0 | ||
|
|
c774bf3311 | ||
|
|
9071d5131a | ||
|
|
c676ca98ff | ||
|
|
690ff3f364 | ||
|
|
04b0106bca | ||
|
|
31233089f1 | ||
|
|
1f5426f939 | ||
|
|
1ec87634d4 | ||
|
|
d22af021ee | ||
|
|
c9ab33eded | ||
|
|
6dcd67a902 | ||
|
|
cb1cf4dc8e | ||
|
|
6cbf69d109 | ||
|
|
e8ec3b1e37 | ||
|
|
f927014d06 | ||
|
|
19a5feb875 | ||
|
|
9dcf3eb68b | ||
|
|
11364918b2 | ||
|
|
1430304d36 | ||
|
|
2a92c2e595 | ||
|
|
fe4d4aeff0 | ||
|
|
23a1710557 | ||
|
|
774de78691 | ||
|
|
3081e5e6e9 | ||
|
|
7428bd3a7f | ||
|
|
55feadff05 | ||
|
|
97e2d15634 | ||
|
|
b245337501 | ||
|
|
bb7d733cde | ||
|
|
aa679ea1d6 | ||
|
|
0e8234abfd | ||
|
|
d5b9029a23 | ||
|
|
671e1fd1c6 | ||
|
|
c144c08112 | ||
|
|
aada3e813d | ||
|
|
335b0f2575 | ||
|
|
b1f01d7a65 | ||
|
|
3b56160d38 | ||
|
|
39e315628e | ||
|
|
e125ab1b9a | ||
|
|
5d3591b853 | ||
|
|
206238893b | ||
|
|
33476b4754 | ||
|
|
2c888f418b | ||
|
|
565106fc1f | ||
|
|
a45217e6b9 | ||
|
|
d7790ca8bc | ||
|
|
8ef8d994df | ||
|
|
80ad635348 | ||
|
|
ec944cf068 | ||
|
|
ba5781c3bf | ||
|
|
d86cb99dd5 | ||
|
|
3204b9804b | ||
|
|
ce735256d3 | ||
|
|
cccf812454 | ||
|
|
f7e1979665 | ||
|
|
49fc5da207 | ||
|
|
5276f56cc4 | ||
|
|
9df6793f34 | ||
|
|
d90e191837 | ||
|
|
d5d448888d | ||
|
|
8d8600b442 | ||
|
|
0bf6455153 | ||
|
|
80b7a7f6ac | ||
|
|
6b789c57e8 | ||
|
|
b8a344fc17 | ||
|
|
1b6319e9cf | ||
|
|
2cc81253ff | ||
|
|
499c694146 | ||
|
|
bc32cca281 | ||
|
|
dead4b4ab6 | ||
|
|
305cb2cdd5 | ||
|
|
287bfcbaa3 | ||
|
|
2a61b751ab | ||
|
|
a830145f36 | ||
|
|
08dc1dd9b9 | ||
|
|
e86b211cd1 | ||
|
|
6c5febc189 | ||
|
|
4d0d60c294 | ||
|
|
16a88ec631 | ||
|
|
1ce2b6b315 | ||
|
|
43a6805902 | ||
|
|
566262c923 | ||
|
|
e4bff281b2 | ||
|
|
9a675912f8 | ||
|
|
f86044e6ce | ||
|
|
43fdaa91a3 | ||
|
|
80f46aefcd | ||
|
|
71f63d7b33 | ||
|
|
8d47cd73c0 | ||
|
|
6d451bc6f9 | ||
|
|
6402e7b755 | ||
|
|
c93f93f637 | ||
|
|
6e51943d15 | ||
|
|
c81cd871f8 | ||
|
|
8ab1dbc373 | ||
|
|
fb26050fab | ||
|
|
c56cd4d5a8 | ||
|
|
de105e8651 | ||
|
|
8e98de6e7c | ||
|
|
6372ca3fac | ||
|
|
3712619f5c | ||
|
|
dee1e77d0b | ||
|
|
d01ed80a61 | ||
|
|
92268b2e76 | ||
|
|
0924654a47 | ||
|
|
8ef742e79d | ||
|
|
64ef13c6e0 | ||
|
|
66ad2c948e | ||
|
|
60e022fedd | ||
|
|
09256b766f | ||
|
|
a951793431 | ||
|
|
f4b8f44d4a | ||
|
|
08ab7d4b59 | ||
|
|
5889001465 | ||
|
|
91d2716122 | ||
|
|
0e6ad28e56 | ||
|
|
fd57909730 | ||
|
|
e3cc75caff | ||
|
|
e26142f43b | ||
|
|
d0f972e128 | ||
|
|
e42fedc820 | ||
|
|
f0c9814c04 | ||
|
|
529278190c | ||
|
|
fcaab36484 | ||
|
|
5dfa995a4b | ||
|
|
c35a990c09 | ||
|
|
11f40bd2cc | ||
|
|
7e8b47d012 | ||
|
|
902aa32dda | ||
|
|
42c0cba7f7 | ||
|
|
f2b84d8d83 | ||
|
|
1b11206174 | ||
|
|
c93e3e9f6f | ||
|
|
9808a0d4d3 | ||
|
|
bd1697dbd2 | ||
|
|
b3b8690bbd | ||
|
|
ad742ec93c | ||
|
|
1de7c38134 | ||
|
|
997943a194 | ||
|
|
47c6048d53 | ||
|
|
a64d459c8e | ||
|
|
a5ad440f17 | ||
|
|
acad24d62a | ||
|
|
989b4cc913 | ||
|
|
38c6627999 | ||
|
|
4b9e18c6b8 | ||
|
|
906f8cc002 | ||
|
|
01ab11644c | ||
|
|
4cf3dcfaae | ||
|
|
b177f84825 | ||
|
|
485e6e0e4d | ||
|
|
516c3411aa | ||
|
|
908354e7fa | ||
|
|
9531dbbc7b | ||
|
|
d10dd1c0b4 | ||
|
|
6533474070 | ||
|
|
576edb53bb | ||
|
|
20e390af85 | ||
|
|
931251a5a8 | ||
|
|
9697550488 | ||
|
|
3dac984613 | ||
|
|
867da56e2e | ||
|
|
719acd3ab1 | ||
|
|
549cae0a06 | ||
|
|
bb45f4f3ba | ||
|
|
b4de6f55c4 | ||
|
|
e99c145d55 | ||
|
|
9cb9f32fbb | ||
|
|
a6f30b6977 | ||
|
|
73692e60d8 | ||
|
|
4abe3d3a49 | ||
|
|
54df4a116c | ||
|
|
715ce2f9ac | ||
|
|
7a98708eef | ||
|
|
d9c08f12a7 | ||
|
|
e41fbc5708 | ||
|
|
634f92efb6 | ||
|
|
98a7b759e8 | ||
|
|
3976685e4e | ||
|
|
f7688bc64e | ||
|
|
18e28294d6 | ||
|
|
39bd0d6463 | ||
|
|
c1819cc027 | ||
|
|
f228d90ca2 | ||
|
|
5f44af3757 | ||
|
|
8a4ae311ce | ||
|
|
ef2434188e | ||
|
|
a014228f7c | ||
|
|
2163c8ae05 | ||
|
|
47bb5184a0 | ||
|
|
f1f1ac3cbd | ||
|
|
f1396c7aad | ||
|
|
21ae48eada | ||
|
|
53e1c1b65c | ||
|
|
858611f95e | ||
|
|
5c334b6c10 | ||
|
|
cf5a02ea0f | ||
|
|
a67bc75b93 | ||
|
|
895ab0c970 | ||
|
|
21f84732c8 | ||
|
|
7eed65e9b4 | ||
|
|
cf5915ad01 | ||
|
|
a4caa87d29 | ||
|
|
bbb3913a36 | ||
|
|
92f07d0418 | ||
|
|
578a642209 | ||
|
|
9d03e4ec0a | ||
|
|
576ad183e7 | ||
|
|
e31596f60e | ||
|
|
ef493b4c0f | ||
|
|
c15312ee70 | ||
|
|
3caefcae49 | ||
|
|
c2f6631f91 | ||
|
|
fb1dfb27df | ||
|
|
898a6a8d8d | ||
|
|
7da53741cd | ||
|
|
47aabc631d | ||
|
|
fb75ac371d | ||
|
|
98c866704a | ||
|
|
e58453d3e6 | ||
|
|
03c62e1ce2 | ||
|
|
2c10545cd8 | ||
|
|
ff2ec7eed1 | ||
|
|
8dfddef6f9 | ||
|
|
73edf4de7b | ||
|
|
cfa58a5661 | ||
|
|
905bff3d59 | ||
|
|
eadcd33e84 | ||
|
|
76fe89dd1f | ||
|
|
3f487c5c28 | ||
|
|
c35a46ec45 | ||
|
|
e3eb933182 | ||
|
|
dacb0e5c72 | ||
|
|
23b24491c3 | ||
|
|
7ab0cf123d | ||
|
|
8f2a4c7231 | ||
|
|
ce53154555 | ||
|
|
c0188ab95a | ||
|
|
ebbd91f87d | ||
|
|
4b0725dfc2 | ||
|
|
350d35fb24 | ||
|
|
8ee3a73dd1 | ||
|
|
b6e4598e7c | ||
|
|
bd2ad99402 | ||
|
|
d26c1199ab | ||
|
|
1ea7c1366a | ||
|
|
b2263fe35e | ||
|
|
bd07907a4c | ||
|
|
ca8931c8af | ||
|
|
46a036ef26 | ||
|
|
e9750b5cab | ||
|
|
0bf0e48698 | ||
|
|
4f1aa97ea9 | ||
|
|
f90f004dea | ||
|
|
559b0833b4 | ||
|
|
31bad290d5 | ||
|
|
2e88f7ead2 | ||
|
|
1a8154c90e | ||
|
|
8fb49ec7ec | ||
|
|
393dad6349 | ||
|
|
2c3db19310 | ||
|
|
472ab626d6 | ||
|
|
2106e2e081 | ||
|
|
d3c80ea5d5 | ||
|
|
6dad25668c | ||
|
|
d862d42e76 | ||
|
|
828b5f053a | ||
|
|
032d1fa9cb | ||
|
|
83ad646734 | ||
|
|
88c25a6a6a | ||
|
|
a254cfc841 | ||
|
|
0d4b9f4ba6 | ||
|
|
bf29fe0e10 | ||
|
|
3df8f8b120 | ||
|
|
38d0e684f1 | ||
|
|
83e9aefff5 | ||
|
|
02ee925103 | ||
|
|
fc69da7a42 | ||
|
|
5dc179ebef | ||
|
|
59e3b907e9 | ||
|
|
fe7629e8fc | ||
|
|
76180d3ea1 | ||
|
|
5c4f8ca246 | ||
|
|
b8530a6b70 | ||
|
|
83686542b2 | ||
|
|
b1551cad98 | ||
|
|
5af6b016c1 | ||
|
|
6abd6d6b47 | ||
|
|
e456a325f9 | ||
|
|
eddad666ff | ||
|
|
ca9a25e860 | ||
|
|
8d9a1b82dd | ||
|
|
f1b57dd9b4 | ||
|
|
d2a0323ae4 | ||
|
|
3a339ba37f | ||
|
|
e9603b0738 | ||
|
|
3d83fd784b | ||
|
|
38a5f891a4 | ||
|
|
8563c8beef | ||
|
|
f91102ee07 | ||
|
|
cc08e9d84a | ||
|
|
075d38117a | ||
|
|
6cc4896690 | ||
|
|
673a6773b2 | ||
|
|
3a6923988d | ||
|
|
0d1692681f | ||
|
|
fcf705e007 | ||
|
|
5c93c214b9 | ||
|
|
7cbb8401a2 | ||
|
|
b3c262cd47 | ||
|
|
45a7b90c6c | ||
|
|
e1c3b4fd94 | ||
|
|
109112ae75 | ||
|
|
a24ba41eda | ||
|
|
be3f8ef80d | ||
|
|
d50dedb5d0 | ||
|
|
74e9e213d6 | ||
|
|
d8d92cae61 | ||
|
|
99d5b4d982 | ||
|
|
52fd32c837 | ||
|
|
061f08bc03 | ||
|
|
735bc98243 | ||
|
|
e53a65ef07 | ||
|
|
3642ffb57a | ||
|
|
3dcc319cd2 | ||
|
|
8484f7b906 | ||
|
|
59018ab632 | ||
|
|
c6cfeb15f4 | ||
|
|
adc7dab377 | ||
|
|
a9e01f4309 | ||
|
|
0269e532df | ||
|
|
4863320e45 | ||
|
|
3ad1ed7dbc | ||
|
|
ae823e6c4e | ||
|
|
9056e5a2dc | ||
|
|
2b20802dbb | ||
|
|
a972d1ef62 | ||
|
|
30c3713dca | ||
|
|
6f58d4c474 | ||
|
|
9d9bac397b | ||
|
|
d8f10c33dc | ||
|
|
5d57eff612 | ||
|
|
43956c1bc8 | ||
|
|
2930900963 | ||
|
|
6404780186 | ||
|
|
5d99e50c4a | ||
|
|
aaeb630eb1 | ||
|
|
3acba59494 | ||
|
|
3760616639 | ||
|
|
026dce563b | ||
|
|
b77febc7a7 | ||
|
|
83601dca2f | ||
|
|
05aeaf1bd2 | ||
|
|
b138867b78 | ||
|
|
a1195cefd5 | ||
|
|
b83c3b3684 | ||
|
|
5502ddaf0d | ||
|
|
f54336eb61 | ||
|
|
18d6884522 | ||
|
|
8ba0109e55 | ||
|
|
f50ca85a95 | ||
|
|
39e6765e64 | ||
|
|
47e20da631 | ||
|
|
bb7b47b063 | ||
|
|
a2618dcde5 | ||
|
|
9fdb126715 | ||
|
|
b2a81c09ec | ||
|
|
04fa5d3feb | ||
|
|
d73108cc13 | ||
|
|
3ba00f91bb | ||
|
|
cbee8580d0 | ||
|
|
6ccd6b009b | ||
|
|
6cf6e20d2e | ||
|
|
93efe71080 | ||
|
|
697c8f129c | ||
|
|
c12f7fef76 | ||
|
|
cde238de94 | ||
|
|
ec83d481fa | ||
|
|
1f12fdbeea | ||
|
|
8743e88550 | ||
|
|
f3c238db1c | ||
|
|
2534a3c767 | ||
|
|
b1f527e682 | ||
|
|
6fa16b615b | ||
|
|
e5c90badba | ||
|
|
be6c6ba976 | ||
|
|
7f3be98199 | ||
|
|
0e498db735 | ||
|
|
7203b740fd | ||
|
|
97aab900da | ||
|
|
dddb2837dd | ||
|
|
7d282426c4 | ||
|
|
1637937664 | ||
|
|
03144eb160 | ||
|
|
53210710ba | ||
|
|
0d98e09fb1 | ||
|
|
e7a972df77 | ||
|
|
cb2f396e33 | ||
|
|
2940d05209 | ||
|
|
2377aa7ac2 | ||
|
|
f18086f83a | ||
|
|
dce3b7ed6c | ||
|
|
5bda4df7fa | ||
|
|
1a8e36ccd3 | ||
|
|
14816c7c81 | ||
|
|
8fdb16c555 | ||
|
|
940439866e | ||
|
|
e91b19d006 | ||
|
|
46905ebe99 | ||
|
|
d364f46baa | ||
|
|
2b53c98cf5 | ||
|
|
36d07d7a15 | ||
|
|
458e479681 | ||
|
|
5fe95570d2 | ||
|
|
c3ce2f8a07 | ||
|
|
d0dab4bb09 | ||
|
|
893356abcd | ||
|
|
00c879e27d | ||
|
|
b65af106ff | ||
|
|
fdd7eb3446 | ||
|
|
22645d9158 | ||
|
|
76dd8613ca | ||
|
|
99f15c507d | ||
|
|
849b887e20 | ||
|
|
245d9a1e46 | ||
|
|
5917d4ef0b | ||
|
|
90053eb9df | ||
|
|
a7304b9a19 | ||
|
|
540929c6a0 | ||
|
|
e456175a81 | ||
|
|
3ff32092a3 | ||
|
|
55d7cf3865 | ||
|
|
ac4ac935f6 | ||
|
|
d83d49d83b | ||
|
|
e36158a0da | ||
|
|
b20028c42b | ||
|
|
5cc14b8031 | ||
|
|
1cda7a9de0 | ||
|
|
49b76f5c71 | ||
|
|
c0474e811d | ||
|
|
40c9709445 | ||
|
|
b67e9905bc | ||
|
|
c74192d578 | ||
|
|
33feb00e8f | ||
|
|
8f16df4c90 | ||
|
|
fb6cb51e64 | ||
|
|
28ebbb8f02 | ||
|
|
bd4ddcdedd | ||
|
|
e621edfba7 | ||
|
|
304a899114 | ||
|
|
8391af2e8f | ||
|
|
69ab6a0e0d | ||
|
|
a216f0db75 | ||
|
|
69260fb96a | ||
|
|
db87e0ae6a | ||
|
|
8ead919fae | ||
|
|
b73c04f3c8 | ||
|
|
f790aeb8f6 | ||
|
|
7b17abc555 | ||
|
|
ffadf5dd51 | ||
|
|
23d8d99925 | ||
|
|
d88df59c32 | ||
|
|
17906735df | ||
|
|
3a6e898b12 | ||
|
|
0cc3df3747 | ||
|
|
2bc842a2b3 | ||
|
|
1c6f640026 | ||
|
|
6daad829cc | ||
|
|
7d926822ed | ||
|
|
d4dcbb13fc | ||
|
|
f396712f59 | ||
|
|
d97250f968 | ||
|
|
e7e8e95242 | ||
|
|
d518a655a8 | ||
|
|
b6a5844027 | ||
|
|
9d9abea157 | ||
|
|
ee1165ea33 | ||
|
|
2704ee54cf | ||
|
|
ad01d28351 | ||
|
|
a215c1cf30 | ||
|
|
cadea2f6c3 | ||
|
|
e13e15d3e9 | ||
|
|
6ef2f67ae8 | ||
|
|
765c4ee9f6 | ||
|
|
a4103d8dc8 | ||
|
|
8e0f021cad | ||
|
|
002ab85f76 | ||
|
|
4a0f69a3f0 | ||
|
|
8a2e96d995 | ||
|
|
13dbd2f5d4 | ||
|
|
6d084428a8 | ||
|
|
312efc3878 | ||
|
|
301faebfcc | ||
|
|
a8af103ff4 | ||
|
|
0df50c3f33 | ||
|
|
08c80f77a9 | ||
|
|
ea8d65d7fc | ||
|
|
e3198b0f6b | ||
|
|
19220de388 | ||
|
|
52878d6c5b | ||
|
|
abfece70c1 | ||
|
|
33da6e9eb8 | ||
|
|
4919a2d2a8 | ||
|
|
2f2e8a560d | ||
|
|
884818934f | ||
|
|
1d8e6f53a1 | ||
|
|
3554267adf | ||
|
|
f7687a2567 | ||
|
|
ebd4a02d2c | ||
|
|
4a354bba86 | ||
|
|
d40c22441f | ||
|
|
6395eda0c8 | ||
|
|
eb6ada8091 | ||
|
|
a7ef686a27 | ||
|
|
e2af492a63 | ||
|
|
84de9ee0da | ||
|
|
e182e669f0 | ||
|
|
a9a28d3e77 | ||
|
|
6a77acdbf2 | ||
|
|
028725468a | ||
|
|
9dbffa6ee8 | ||
|
|
2d3f3cae13 | ||
|
|
fb9f0f3ee8 | ||
|
|
ab276504fd | ||
|
|
3cc4e5b440 | ||
|
|
b2664bc469 | ||
|
|
7d5afdebe1 | ||
|
|
3bbc7fb328 | ||
|
|
ac6ad2dea1 | ||
|
|
0b116f1b5c | ||
|
|
acdb934ef9 | ||
|
|
5591a1a4e8 | ||
|
|
124574bb3a | ||
|
|
a2cfaab7f4 | ||
|
|
6355425a6f | ||
|
|
2d96995801 | ||
|
|
3fc4daa447 | ||
|
|
c7ff24b983 | ||
|
|
3f674faf30 | ||
|
|
b9ad1b6b26 | ||
|
|
676f0ddc2e | ||
|
|
6c60dc5dc8 | ||
|
|
1af5ade39a | ||
|
|
ad40d33400 | ||
|
|
5017e2302b | ||
|
|
3bfeda4a3b | ||
|
|
348b1b4dda | ||
|
|
0fd7e7f040 | ||
|
|
cfa0fa7243 | ||
|
|
6a63d9df0a | ||
|
|
36646eb527 | ||
|
|
48940bf4c0 | ||
|
|
5346a386f7 | ||
|
|
b3201ad073 | ||
|
|
35b0ba6d07 | ||
|
|
3c087c6716 | ||
|
|
854946e313 | ||
|
|
d6a1d7a913 | ||
|
|
700b425774 | ||
|
|
e31634b0fb | ||
|
|
1f06176149 | ||
|
|
e628026cf0 | ||
|
|
3a512c300e | ||
|
|
7f9e7c73ab | ||
|
|
3e7be6cc0f | ||
|
|
81dfe96355 | ||
|
|
efa23bd39b | ||
|
|
6aa4b1b301 | ||
|
|
304cbef5ed | ||
|
|
263968e019 | ||
|
|
c05521e55a | ||
|
|
2f3c71feaa | ||
|
|
0b710a86a9 | ||
|
|
2e37d2c253 | ||
|
|
d7c1dc5517 | ||
|
|
77b9fd62a7 | ||
|
|
f838db4e18 | ||
|
|
b2d7124424 | ||
|
|
2532c4a39e | ||
|
|
be19585c68 | ||
|
|
ca0cbad1c7 | ||
|
|
fb53452d37 | ||
|
|
b5246f3f09 | ||
|
|
4be413af79 | ||
|
|
5db2de95f5 | ||
|
|
6418add83d | ||
|
|
7d26c51da6 | ||
|
|
dcada79e06 | ||
|
|
37384c583d | ||
|
|
9544783b5e | ||
|
|
eaf9b319ca | ||
|
|
47abde2f8d | ||
|
|
30325e4f32 | ||
|
|
9cf38f8705 | ||
|
|
7de4803e21 | ||
|
|
9586a7ddcd | ||
|
|
a4f6c8bf7b | ||
|
|
f5ab6fc602 | ||
|
|
222fb1c0e7 | ||
|
|
511fe7c51e | ||
|
|
acb3cc80b7 | ||
|
|
23fd0982b0 | ||
|
|
d2a159d2dc | ||
|
|
dc0bfeb0cc | ||
|
|
deea0f7e4f | ||
|
|
3a33f4c0a6 | ||
|
|
312872adaf | ||
|
|
ba5e3a81e0 | ||
|
|
bf5c32d780 | ||
|
|
d3cb38de29 | ||
|
|
047ed52d60 | ||
|
|
bb96bb9a88 | ||
|
|
0ee672d2b0 | ||
|
|
2a8a6b3970 | ||
|
|
5dbc51da59 | ||
|
|
f1a6d938cd | ||
|
|
991a2b1873 | ||
|
|
172c01561b | ||
|
|
b2f061cbaf | ||
|
|
1f1b2977a4 | ||
|
|
4a0a7bc424 | ||
|
|
8fbb6d7c62 | ||
|
|
0299467831 | ||
|
|
2efe240617 | ||
|
|
ed543dc648 | ||
|
|
db6295c917 | ||
|
|
d54a42f0f0 | ||
|
|
74ae6651c8 | ||
|
|
f33f352501 | ||
|
|
39c17e71ef | ||
|
|
081637134f | ||
|
|
39165a8694 | ||
|
|
ad163ce244 | ||
|
|
a7176d39f0 | ||
|
|
f1c185b771 | ||
|
|
103e1e8d24 | ||
|
|
30198c4bdd | ||
|
|
841f02f43f | ||
|
|
a5e9861440 | ||
|
|
d69698c23f | ||
|
|
d763f14ffe | ||
|
|
22918152cc | ||
|
|
1fcee242dc | ||
|
|
3f99c15338 | ||
|
|
f496f015b6 | ||
|
|
5e7e9d5b6c | ||
|
|
8bd4ca49a8 | ||
|
|
d33f7e08a8 | ||
|
|
d46ad592b5 | ||
|
|
eda765453b | ||
|
|
b295fc6687 | ||
|
|
0959608ab9 | ||
|
|
6db94dbb9a | ||
|
|
04a3c9d9ee | ||
|
|
db4d1f5768 | ||
|
|
81d6219663 | ||
|
|
3a1b4ffcb8 | ||
|
|
d6fe1a65eb | ||
|
|
72bbe9fdf0 | ||
|
|
d125ece9e9 | ||
|
|
ecb99c963d | ||
|
|
9738079c42 | ||
|
|
e9e27ca47c | ||
|
|
5d21fb26e6 | ||
|
|
bcf3f8611a | ||
|
|
d351e316bf | ||
|
|
dc6384d063 | ||
|
|
914e2fa35f | ||
|
|
8b96081579 | ||
|
|
f3e0623d1d | ||
|
|
abcaee24f9 | ||
|
|
8951660393 | ||
|
|
e4ecbad3cb | ||
|
|
40a740b45c | ||
|
|
9af7f506f0 | ||
|
|
9b8558dbde | ||
|
|
d28ca67edb | ||
|
|
0deaba0920 | ||
|
|
bcb10ba6da | ||
|
|
ef268e2320 | ||
|
|
d9814c5542 | ||
|
|
dd3b9dd01c | ||
|
|
1b43bc99a1 | ||
|
|
eccde6c0c0 | ||
|
|
69a2a5b551 | ||
|
|
bc9e895e25 | ||
|
|
457c5b8b3b | ||
|
|
9f1aedb56d | ||
|
|
2cefb42559 | ||
|
|
a048aa94ec | ||
|
|
27d359bd43 | ||
|
|
456b4801af | ||
|
|
82582e5a5b | ||
|
|
18e81c4b90 | ||
|
|
bad0034e5d | ||
|
|
99d5ff7347 | ||
|
|
dc579417fe | ||
|
|
fe906dabda | ||
|
|
8ab75e7109 | ||
|
|
aa2b3d3da1 | ||
|
|
0a1b71f125 | ||
|
|
757a3685f2 | ||
|
|
fd2c3c9857 | ||
|
|
84477ff212 | ||
|
|
1d7ccaece6 | ||
|
|
ce2525d4d8 | ||
|
|
7be9e880c2 | ||
|
|
7233931681 | ||
|
|
d7e111fb71 | ||
|
|
2ac191fbb8 | ||
|
|
088140aca4 | ||
|
|
e08d0671ab | ||
|
|
7669378c6e | ||
|
|
1494082a2a | ||
|
|
233c2bd882 | ||
|
|
9c4f09a50a | ||
|
|
89d982a8e4 | ||
|
|
9d3ee3d56e | ||
|
|
44421bbc79 | ||
|
|
320558a782 | ||
|
|
9ef7ddbf20 | ||
|
|
603f994f3f | ||
|
|
ada35e0e00 | ||
|
|
fc778006ef | ||
|
|
11760afddd | ||
|
|
d78ae309f1 | ||
|
|
73fd9e4dfa | ||
|
|
fb9cf60c41 | ||
|
|
b6a329d479 | ||
|
|
70bc7b39b7 | ||
|
|
03777067cd | ||
|
|
f5271431fb | ||
|
|
c30eeee5d8 | ||
|
|
dac02bef8c | ||
|
|
32edaee3a2 | ||
|
|
ff1c58def4 | ||
|
|
f9372f5578 | ||
|
|
6afc16c33b | ||
|
|
74a3d2028f | ||
|
|
dfe468f335 | ||
|
|
4f7721b405 | ||
|
|
3abd12aee3 | ||
|
|
1c90a77325 | ||
|
|
671219ae56 | ||
|
|
78fa7374d9 | ||
|
|
c1b389ad9b | ||
|
|
5a07a51b5d | ||
|
|
824b9803d2 | ||
|
|
ab72e48431 | ||
|
|
78b7ae72c9 | ||
|
|
1151856d38 | ||
|
|
12c282ce5c | ||
|
|
0ac822c577 | ||
|
|
400282282f | ||
|
|
789c505a88 | ||
|
|
0429bb0ab8 | ||
|
|
000eb0916e | ||
|
|
4db1fecba8 | ||
|
|
013ad94af0 | ||
|
|
2ceb8030ee | ||
|
|
47ac514835 | ||
|
|
5e0c9595c3 | ||
|
|
a0747aa960 | ||
|
|
07912fdecd | ||
|
|
9a33943783 | ||
|
|
8981ddb681 | ||
|
|
7d61a79a78 | ||
|
|
afa61aeb09 | ||
|
|
bf57aa1df0 | ||
|
|
055e3bf609 | ||
|
|
b1dadaf15d | ||
|
|
9e400911f5 | ||
|
|
892b875867 | ||
|
|
8f7bc1ffbb | ||
|
|
e5506d40bc | ||
|
|
64f89c5eda | ||
|
|
1ad0665eb5 | ||
|
|
37309c23c2 | ||
|
|
8983ddbdcc | ||
|
|
d99a21eb8d | ||
|
|
f9ce1c607b | ||
|
|
847312fcf9 | ||
|
|
b770076b7f | ||
|
|
dc9413258e | ||
|
|
4b574a2863 | ||
|
|
4b3cc67353 | ||
|
|
32b72756f3 | ||
|
|
2fc86e2833 | ||
|
|
fab472859d | ||
|
|
92caa3a186 | ||
|
|
26c7a96255 | ||
|
|
e170e463fe | ||
|
|
899daa9ea7 | ||
|
|
6d334c05e9 | ||
|
|
5ac0cc51d3 | ||
|
|
f93c2b161d | ||
|
|
6b071c0fb2 | ||
|
|
d3245a43d3 | ||
|
|
90a51c2cc1 | ||
|
|
61df5e0a37 | ||
|
|
c0312f9b50 | ||
|
|
eb70f05168 | ||
|
|
505db38232 | ||
|
|
096e1e3caa | ||
|
|
b5d8b51310 | ||
|
|
c9e7201058 | ||
|
|
4bf705a3d3 | ||
|
|
ce42568721 | ||
|
|
eb956b2449 | ||
|
|
1bf4e93da1 | ||
|
|
aba0a8421b | ||
|
|
b5a58e6ca0 | ||
|
|
44aa7464e1 | ||
|
|
4ea684dd7a | ||
|
|
215b7e08f8 | ||
|
|
754911f346 | ||
|
|
9873106785 | ||
|
|
d005359f89 | ||
|
|
1ce52a2845 | ||
|
|
7e480d1ff9 | ||
|
|
85877d259c | ||
|
|
0b86db8748 | ||
|
|
bca7f62efd | ||
|
|
4953ae84cd | ||
|
|
e96a5a0b3e | ||
|
|
e4678f4709 | ||
|
|
1def13deb3 | ||
|
|
bce4283239 | ||
|
|
9ff786d021 | ||
|
|
ee14a67795 | ||
|
|
b63a2e37be | ||
|
|
84274b4259 | ||
|
|
b6bf5298e6 | ||
|
|
b0d5ffec8f | ||
|
|
09ff81c411 | ||
|
|
a0293578b1 | ||
|
|
4595403a99 | ||
|
|
0f73884c8d | ||
|
|
2e9cbdcb0d | ||
|
|
a652d892ca | ||
|
|
581252febc | ||
|
|
b27d283f21 | ||
|
|
f2d7c49acf | ||
|
|
a397a23a9c | ||
|
|
9f7e179288 | ||
|
|
ad1c3d2438 | ||
|
|
51adf81918 | ||
|
|
97718a0a25 | ||
|
|
1aaba440b5 | ||
|
|
b8f2b8948f | ||
|
|
d96d49329b | ||
|
|
4db421ca36 | ||
|
|
c3991c8164 | ||
|
|
e904bab206 | ||
|
|
500ccd8e80 | ||
|
|
7cf7311a9d | ||
|
|
0669edddae | ||
|
|
38a8d7742e | ||
|
|
32e84d2316 | ||
|
|
151b86cb7b | ||
|
|
e4c9bebe34 | ||
|
|
8d5cb00bec | ||
|
|
15530a4820 | ||
|
|
f6e56b345d | ||
|
|
56d61eb44f | ||
|
|
2103da7b9d | ||
|
|
679069729c | ||
|
|
f764448ccc | ||
|
|
e1828696f7 | ||
|
|
5b87380749 | ||
|
|
917d0dfc49 | ||
|
|
191839f764 | ||
|
|
316cf057f3 | ||
|
|
55be212594 | ||
|
|
489e63f8e7 | ||
|
|
62c081dc85 | ||
|
|
023ad9ddf8 | ||
|
|
eccf486162 | ||
|
|
a6da46a00e | ||
|
|
747d2c97cd | ||
|
|
af2969dec5 | ||
|
|
53dba8678c | ||
|
|
afdac9b413 | ||
|
|
1ad280db98 | ||
|
|
035c3ad319 | ||
|
|
c237a1c0d2 | ||
|
|
f1d093548e | ||
|
|
beab74adf5 | ||
|
|
2a49e8a931 | ||
|
|
395857c37c | ||
|
|
9a34f25edc | ||
|
|
0af02fb9ae | ||
|
|
dcff8794ad | ||
|
|
1b4f5b13f1 | ||
|
|
3950818030 | ||
|
|
d6da2ef096 | ||
|
|
455298d736 | ||
|
|
d99856c52b | ||
|
|
087ec11e6a | ||
|
|
00c0a84e4e | ||
|
|
be229b1ac6 | ||
|
|
8106981bb6 | ||
|
|
de4d7cd10d | ||
|
|
804dcac12f | ||
|
|
fb0987b824 | ||
|
|
88f50a66ff | ||
|
|
7be600d8e9 | ||
|
|
11d6b8029f | ||
|
|
f1d4c01190 | ||
|
|
c12d93e77f | ||
|
|
204130a598 | ||
|
|
dbd45d4173 | ||
|
|
7e0bfbbad2 | ||
|
|
db18e1480e | ||
|
|
9baa27508a | ||
|
|
c3267def97 | ||
|
|
390927772e | ||
|
|
a8bec4ec9c | ||
|
|
167e283450 | ||
|
|
0c3254fd48 | ||
|
|
0faf2f0461 | ||
|
|
dd6e42aacc | ||
|
|
18e5e9dcc5 | ||
|
|
c8f44ab460 | ||
|
|
ac1f9c790a | ||
|
|
7533996fac | ||
|
|
1721571012 | ||
|
|
4358a04730 | ||
|
|
c552d912a0 | ||
|
|
ad7ce085f7 | ||
|
|
828edb3a43 | ||
|
|
4cb64580fd | ||
|
|
5b2fa128a4 | ||
|
|
b7abb64661 | ||
|
|
66424b7ed5 | ||
|
|
81dafb7b3f | ||
|
|
cea81c2dc1 | ||
|
|
4b1e99ef93 | ||
|
|
83120a5bea | ||
|
|
20723896e1 | ||
|
|
aed4859642 | ||
|
|
d0ade1d190 | ||
|
|
fb8e35bb44 | ||
|
|
ce351f5c38 | ||
|
|
26ee1c4547 | ||
|
|
bf327f3916 | ||
|
|
e3dd6d8c88 | ||
|
|
137fe12c43 | ||
|
|
a2fed200fe | ||
|
|
efeeef214b | ||
|
|
37617c67f8 | ||
|
|
56f675f188 | ||
|
|
7e7dc7694c | ||
|
|
8cf8da5776 | ||
|
|
b59705bed4 | ||
|
|
3b909253bb | ||
|
|
98f90340f3 | ||
|
|
a4c9bf7d30 | ||
|
|
f459eaa5ea | ||
|
|
8d8b874c20 | ||
|
|
ccceaeaca2 | ||
|
|
076e93184b | ||
|
|
c352b296da | ||
|
|
9e04eec9dd | ||
|
|
0e19f88a04 | ||
|
|
e788e8fa0f | ||
|
|
a56c406aa3 | ||
|
|
a3457d9408 | ||
|
|
b69fed18e2 | ||
|
|
2964aea447 | ||
|
|
587488a1b1 | ||
|
|
623b394c83 | ||
|
|
e671ffdab1 | ||
|
|
92d1080b2f | ||
|
|
893c0e9b67 | ||
|
|
af60f71ea3 | ||
|
|
9a952f1004 | ||
|
|
3ec7dfff8b | ||
|
|
d30a5e0388 | ||
|
|
fcece7e189 | ||
|
|
3949d9633c | ||
|
|
62c1c5f38b | ||
|
|
56204c5748 | ||
|
|
34c163be88 | ||
|
|
11002d4a56 | ||
|
|
240f27ce97 | ||
|
|
5295be1c25 | ||
|
|
238a67af3a | ||
|
|
4382234676 | ||
|
|
8e5c93a31f | ||
|
|
0e5d72dc5d | ||
|
|
4b8069f5ec | ||
|
|
a816a48416 | ||
|
|
5415440829 | ||
|
|
9668272b80 | ||
|
|
15e19489e3 | ||
|
|
2083f683ad | ||
|
|
c3610aa43c | ||
|
|
df4fbc272a | ||
|
|
9698a995fb | ||
|
|
c1ac3aa483 | ||
|
|
311bdbd360 | ||
|
|
291f111913 | ||
|
|
95e10bdb9e | ||
|
|
c2a6dcb6bd | ||
|
|
61c4bb9888 | ||
|
|
3439746645 | ||
|
|
b10fe465ab | ||
|
|
c6b171ba95 | ||
|
|
5a17d6cd5f | ||
|
|
480af2644c | ||
|
|
ecd2e06883 | ||
|
|
4f3ae23170 | ||
|
|
7cfb33d0ef | ||
|
|
9224ab1592 | ||
|
|
a696ff37f1 | ||
|
|
931a996dab | ||
|
|
68c03090a3 | ||
|
|
98fe46757f | ||
|
|
cefd137634 | ||
|
|
6b6e887c2f | ||
|
|
20cd4f806a | ||
|
|
b92303b1c9 | ||
|
|
59d23e05b1 | ||
|
|
731a36d3a0 | ||
|
|
162fc0720e | ||
|
|
342bbaa3ae | ||
|
|
f086ef5cad | ||
|
|
56a3ee5fe6 | ||
|
|
d80d532a2a | ||
|
|
3aca14d530 | ||
|
|
aa2d3962bf | ||
|
|
f7c717e393 | ||
|
|
268fea58ee | ||
|
|
87cdc5ad1c | ||
|
|
ba140a8a84 | ||
|
|
27f1181d53 | ||
|
|
f953e6adb8 | ||
|
|
ffd14fe7d9 | ||
|
|
3206c2100d | ||
|
|
66fa12a091 | ||
|
|
b1bdf23d9c | ||
|
|
12bf07d560 | ||
|
|
132650df28 | ||
|
|
81a77949fc | ||
|
|
e597f98c62 | ||
|
|
7fbb2b195f | ||
|
|
1feaa7fed7 | ||
|
|
9b82ae19b0 | ||
|
|
9d3c13065b | ||
|
|
4859f8f759 | ||
|
|
ac284fd39c | ||
|
|
fdef0db87c | ||
|
|
e78db000c6 | ||
|
|
032ea8a8d3 | ||
|
|
fc63f66e89 | ||
|
|
832e626573 | ||
|
|
cc7d352209 | ||
|
|
ce5d9a2ee8 | ||
|
|
77c51d3ae7 | ||
|
|
53dae45430 | ||
|
|
16343ffe70 | ||
|
|
b37498d5f6 | ||
|
|
7ad16e5b0c | ||
|
|
9f41906895 | ||
|
|
2af8daff1d | ||
|
|
fbeb379f1b | ||
|
|
9577735ff7 | ||
|
|
2dcd50c11b | ||
|
|
862c223e11 | ||
|
|
7f4d5aeb0e | ||
|
|
30681eb772 | ||
|
|
52e575e1e7 | ||
|
|
890e12c306 | ||
|
|
6cbf6b7875 | ||
|
|
c255a84941 | ||
|
|
ce7d6d69d9 | ||
|
|
d5538b7076 | ||
|
|
cdfa13b265 | ||
|
|
e5efc91ef4 | ||
|
|
e31c911c30 | ||
|
|
a658ea1573 | ||
|
|
6d5b88d7b9 | ||
|
|
a986e72338 | ||
|
|
162d9b6c2e | ||
|
|
f7f49d27c5 | ||
|
|
9e3ccf4b3e | ||
|
|
6b71c2f392 | ||
|
|
0d313a3964 | ||
|
|
75a0a6752a | ||
|
|
363fc8deb5 | ||
|
|
ddac192c4a | ||
|
|
69a03c2e16 | ||
|
|
2b128b85f7 | ||
|
|
b09f973231 | ||
|
|
95815a558c | ||
|
|
879da03438 | ||
|
|
d022be547b | ||
|
|
3f83fdbfc1 | ||
|
|
949152532c | ||
|
|
215adab1f9 | ||
|
|
7ce46ed60c | ||
|
|
c32bcca67b | ||
|
|
cb442364ca | ||
|
|
6bdc01290d | ||
|
|
ac34bf1e54 | ||
|
|
6fb164d200 | ||
|
|
a5d300c6ff | ||
|
|
6eb4409a72 | ||
|
|
533677df8b | ||
|
|
8f27b2ab56 | ||
|
|
25be42d385 | ||
|
|
00f6d30e08 | ||
|
|
090822eb41 | ||
|
|
d9900a725d | ||
|
|
a10106c61a | ||
|
|
5cb01f2ae9 | ||
|
|
4c1efe7ad4 | ||
|
|
4be92f285a | ||
|
|
f9b89e98c2 | ||
|
|
be01ce03d0 | ||
|
|
f221441877 | ||
|
|
18fda7ec68 | ||
|
|
f2e8c00f49 | ||
|
|
30e8b818f5 | ||
|
|
525ce0e0ad | ||
|
|
3cd567dc95 | ||
|
|
2f7ffa3636 | ||
|
|
d99386ef1e | ||
|
|
9ae3d2c074 | ||
|
|
dd5a337a49 | ||
|
|
51e634ccb4 | ||
|
|
31b1a821ca | ||
|
|
bf13fd48ce | ||
|
|
3b99760a42 | ||
|
|
0e78dc35d8 | ||
|
|
c8bbdb23de | ||
|
|
7ee8117186 | ||
|
|
8237c41143 | ||
|
|
d52ca93ba6 | ||
|
|
8354651059 | ||
|
|
81cc3c260f | ||
|
|
4dc32e194b | ||
|
|
5a82dd5110 | ||
|
|
f20708a5e7 | ||
|
|
91cf78f183 | ||
|
|
0cde8819cf | ||
|
|
07632b0eeb | ||
|
|
4a7f825cfe | ||
|
|
0b6b068097 | ||
|
|
4bc2051f44 | ||
|
|
623b2306ca | ||
|
|
34dde53506 | ||
|
|
7a09182446 | ||
|
|
233e513860 | ||
|
|
eb8cf56e8e | ||
|
|
12a27643db | ||
|
|
c6ccde0558 | ||
|
|
16e3ebd87b | ||
|
|
94c096dd5b | ||
|
|
2e3e4ec3b2 | ||
|
|
6e222c3938 | ||
|
|
3b3bd9b6c9 | ||
|
|
4e3331ba66 | ||
|
|
7caa96abcd | ||
|
|
b2776269cf | ||
|
|
b6c5a5fc9a | ||
|
|
94943a9a84 | ||
|
|
4c1942e3fe | ||
|
|
71e72f215d | ||
|
|
58cdfd86d0 | ||
|
|
dfa66b9dd4 | ||
|
|
d56ea25816 | ||
|
|
c91b272648 | ||
|
|
ca8bb75b40 | ||
|
|
36eab713a1 | ||
|
|
7133576fe9 | ||
|
|
effffcba1d | ||
|
|
404ce8bc3e | ||
|
|
a91bd095b0 | ||
|
|
fd6a1e5ed0 | ||
|
|
7d6ac87033 | ||
|
|
8aa813b862 | ||
|
|
95aa5c9f1c | ||
|
|
4319447cb5 | ||
|
|
50ea162251 | ||
|
|
9c239804d3 | ||
|
|
a7ccb9243d | ||
|
|
320e31bb10 | ||
|
|
8b55a16986 | ||
|
|
f9b8f9a45f | ||
|
|
41125ea1e2 | ||
|
|
73219bf2d2 | ||
|
|
d6eb723b7f | ||
|
|
993d73762c | ||
|
|
48b51c451a | ||
|
|
3d191d5884 | ||
|
|
955133f173 | ||
|
|
5054b714e2 | ||
|
|
c2cafb4b45 | ||
|
|
05868b541b | ||
|
|
67f474ef42 | ||
|
|
a40424e75c | ||
|
|
cd6c0e1de9 | ||
|
|
a99c8219bd | ||
|
|
a03fdaba39 | ||
|
|
92be0033a8 | ||
|
|
6f301576eb | ||
|
|
e2b3f76a10 | ||
|
|
b934c1be6a | ||
|
|
145b50a320 | ||
|
|
a33cdc9c7b | ||
|
|
62101e85ff | ||
|
|
0a3714e5e0 | ||
|
|
86a2830d75 | ||
|
|
b277202838 | ||
|
|
a4f6d9f6e7 | ||
|
|
9300e97d2b | ||
|
|
1d4aa44d3d | ||
|
|
3792f75281 | ||
|
|
b52fcb8aa9 | ||
|
|
a14c794255 | ||
|
|
aef96e95e8 | ||
|
|
f0da63a8ff | ||
|
|
cc860804f6 | ||
|
|
f38c460588 | ||
|
|
d8a19b5565 | ||
|
|
1c5b5e2ce6 | ||
|
|
9b9c59766f | ||
|
|
fc2a202afa | ||
|
|
4b4b71ff32 | ||
|
|
9358838dab | ||
|
|
2f24e42dc1 | ||
|
|
0c12aa163e | ||
|
|
a4d9f702e4 | ||
|
|
ec47274fbd | ||
|
|
efcedabee0 | ||
|
|
25a7b66296 | ||
|
|
ac194cd34f | ||
|
|
04ccb06e3f | ||
|
|
d31ee20ba5 | ||
|
|
9b25d45b93 | ||
|
|
eca05e6bad | ||
|
|
84bf20152b | ||
|
|
d51abdd73e | ||
|
|
200e9f1a8e | ||
|
|
7dc09b4019 | ||
|
|
dbb196a17e | ||
|
|
05a95c699f | ||
|
|
9ea8b2237a | ||
|
|
9c5e340fb8 | ||
|
|
e86c2e5970 | ||
|
|
67006add53 | ||
|
|
caeb86843d | ||
|
|
1571b26a65 | ||
|
|
0f15608175 | ||
|
|
705991e5b0 | ||
|
|
b636874bd9 | ||
|
|
965e4e9b19 | ||
|
|
af77977fda | ||
|
|
e74baf188f | ||
|
|
663a71255f | ||
|
|
bdf2f22f81 | ||
|
|
79aa3e159d | ||
|
|
95118398dd | ||
|
|
4d18a8e55f | ||
|
|
3bab41f138 | ||
|
|
a8330773ca | ||
|
|
4ca2305693 | ||
|
|
f577af0886 | ||
|
|
aab47bd453 | ||
|
|
445ddd89fb | ||
|
|
6f21a96238 | ||
|
|
c47bcb2f54 | ||
|
|
b0b628ffc2 | ||
|
|
428e1bc14d | ||
|
|
d66bb84924 | ||
|
|
4ce5123a12 | ||
|
|
4b4a2e9f9e | ||
|
|
58afd0b604 | ||
|
|
4352456129 | ||
|
|
bb141a70e8 | ||
|
|
ff260c03ca | ||
|
|
96a1192474 | ||
|
|
297f862ccc | ||
|
|
c052f40ef8 | ||
|
|
98246c0e35 | ||
|
|
8ac067da89 | ||
|
|
0ffb5d253a | ||
|
|
3a9898a6a6 | ||
|
|
693ec14df5 | ||
|
|
fa189b3234 | ||
|
|
3b27cd093b | ||
|
|
141bbfb051 | ||
|
|
663a919ed1 | ||
|
|
483babe3bc | ||
|
|
6abb9da88a | ||
|
|
b407641049 | ||
|
|
d5e8807756 | ||
|
|
7e9fdb3555 | ||
|
|
32e07c22d0 | ||
|
|
d427c52aac | ||
|
|
eb623a84d5 | ||
|
|
07290277ba | ||
|
|
743541218f | ||
|
|
94de0a7ce2 | ||
|
|
36e9fb292b | ||
|
|
2661e010d9 | ||
|
|
7687becfee | ||
|
|
1641f09dc9 | ||
|
|
b42faea2eb | ||
|
|
1505673393 | ||
|
|
635a6279a9 | ||
|
|
404d3e0959 | ||
|
|
f77b20bbca | ||
|
|
1d0a1664e6 | ||
|
|
410afbf9a1 | ||
|
|
aaddfa6f3a | ||
|
|
2d9a16e857 | ||
|
|
1dcba51092 | ||
|
|
7c63b30de1 | ||
|
|
c0eae1ad52 | ||
|
|
c012b98223 | ||
|
|
559493babd | ||
|
|
990ab2c7ef | ||
|
|
437003de29 | ||
|
|
629e05b7b1 | ||
|
|
22b1959333 | ||
|
|
e98f6ae570 | ||
|
|
0b5bf0c098 | ||
|
|
1deefa48ee | ||
|
|
97008305ff | ||
|
|
1a17083e8c | ||
|
|
b6664cc859 | ||
|
|
50c4aef873 | ||
|
|
cf42d31214 | ||
|
|
00caa1c0a0 | ||
|
|
93c8ba920a | ||
|
|
8702c04d39 | ||
|
|
e595c313a1 | ||
|
|
955da2e360 | ||
|
|
04b3fc0268 | ||
|
|
105ccc81a5 | ||
|
|
c349892c5b | ||
|
|
3d4b8ce99b | ||
|
|
3571307df5 | ||
|
|
64fd87134f | ||
|
|
82bba44538 | ||
|
|
df05f3a3c0 | ||
|
|
8e31ef7be6 | ||
|
|
f4555f7c96 | ||
|
|
8408da55ea | ||
|
|
4a67dd2e28 | ||
|
|
bd806a34d8 | ||
|
|
2f7e833a79 | ||
|
|
c17503ab78 | ||
|
|
19f76d34db | ||
|
|
25c8b2fabb | ||
|
|
bfd8bf9ca4 | ||
|
|
e6adbb0e42 | ||
|
|
11fc6be328 | ||
|
|
7a5405d2ab | ||
|
|
b9a24f00ad | ||
|
|
dbfc292353 | ||
|
|
a09255b2ff | ||
|
|
9d1c72cc07 | ||
|
|
09ac30ef2e | ||
|
|
0ec8f5d283 | ||
|
|
b872df0f31 | ||
|
|
0add4af208 | ||
|
|
298cd9e065 | ||
|
|
b715d20385 | ||
|
|
79e313a0c0 | ||
|
|
9f4c75d1c2 | ||
|
|
b37492644c | ||
|
|
04a792a8c2 | ||
|
|
35ec24c3f0 | ||
|
|
9a00ccdacc | ||
|
|
61b23677d1 | ||
|
|
90037dc6cd | ||
|
|
e8d48e1f43 | ||
|
|
a2f8c9c75b | ||
|
|
5fb83e7f52 | ||
|
|
dd6bf568d1 | ||
|
|
00ee164cef | ||
|
|
448071b02d | ||
|
|
4dad9d0e37 | ||
|
|
3a2117c5d3 | ||
|
|
26a3f6ddc3 | ||
|
|
7741312673 | ||
|
|
954a1723f1 | ||
|
|
87285d94f7 | ||
|
|
d260d0c182 | ||
|
|
137eb40fab | ||
|
|
af440460e1 | ||
|
|
a5c8472a37 | ||
|
|
dfae37421d | ||
|
|
438a8d8b75 | ||
|
|
ac2034561d | ||
|
|
c42cd4233d | ||
|
|
5b2a73e3eb | ||
|
|
6f163a6ba5 | ||
|
|
cc94cc7d01 | ||
|
|
94934ae2cf | ||
|
|
e361f88501 | ||
|
|
708c042b61 | ||
|
|
600599f49e | ||
|
|
1fe7bbbbc4 | ||
|
|
f83d7a7cd1 | ||
|
|
7094047b3d | ||
|
|
11d3607688 | ||
|
|
fcae58d355 | ||
|
|
ef9ace9e65 | ||
|
|
22e4039133 | ||
|
|
4971670e56 | ||
|
|
e16cab6b9c | ||
|
|
a643c3dba6 | ||
|
|
51abf5b0a6 | ||
|
|
1cee6e309b | ||
|
|
0777a660bf | ||
|
|
5e0479e414 | ||
|
|
942c77816d | ||
|
|
8e260d5c40 | ||
|
|
7951eee8a3 | ||
|
|
be2f7d7a8a | ||
|
|
59c8e8b46e | ||
|
|
98c8b28bf3 | ||
|
|
7bb5bc01b7 | ||
|
|
1482c07ae4 | ||
|
|
adba84ae6a | ||
|
|
146e296826 | ||
|
|
28c10dba09 | ||
|
|
e646a0840d | ||
|
|
74ea6bf00a | ||
|
|
d7ad784809 | ||
|
|
642bd10dcc | ||
|
|
7c566c36f4 | ||
|
|
dbbe038939 | ||
|
|
e3430a916c | ||
|
|
ea1f041e11 | ||
|
|
0fe6d9f367 | ||
|
|
46e7359372 | ||
|
|
41cace9a96 | ||
|
|
4638331cb4 | ||
|
|
e339a7583c | ||
|
|
0b7570c9ee | ||
|
|
a85acfcfc5 | ||
|
|
3d4ccbec23 | ||
|
|
2f66ec60db | ||
|
|
f1cfe2b07b | ||
|
|
6160ca6e30 | ||
|
|
b621c3e4c4 | ||
|
|
64d2ae9ad4 | ||
|
|
39fc45b8d8 | ||
|
|
fd954adc81 | ||
|
|
8b379cbf56 | ||
|
|
59c0b04602 | ||
|
|
11b3cf3bfd | ||
|
|
9254f5a8a5 | ||
|
|
e5b68f4a3c | ||
|
|
95babc01e3 | ||
|
|
4dd792a49f | ||
|
|
207c50e500 | ||
|
|
763e34e861 | ||
|
|
b895a0c335 | ||
|
|
c5767eb545 | ||
|
|
94fb79c17f | ||
|
|
6856b02aa7 | ||
|
|
04f812c136 | ||
|
|
8783cf03b2 | ||
|
|
4e1156e083 | ||
|
|
1d6e1d416b | ||
|
|
fd02e5a07e | ||
|
|
937056fcaf | ||
|
|
41ed18684d | ||
|
|
96d4a22215 | ||
|
|
6e4ef508e8 | ||
|
|
4437d7f3c4 | ||
|
|
001570e941 | ||
|
|
28c41294bb | ||
|
|
82898da507 | ||
|
|
eabcdbf129 | ||
|
|
5ab11edad2 | ||
|
|
b57317bdc2 | ||
|
|
1f49f29183 | ||
|
|
638fbfabdc | ||
|
|
16de12a3ba | ||
|
|
1316578ba3 | ||
|
|
1926c50f09 | ||
|
|
b858a4a5d7 | ||
|
|
ec9741443b | ||
|
|
fe7b2a36ec | ||
|
|
2d88a726b7 | ||
|
|
a51edd3579 | ||
|
|
b7ede8f9ba | ||
|
|
15f36cc19d | ||
|
|
95edd970bc | ||
|
|
2c6285d4b3 | ||
|
|
1d1cdb5ea4 | ||
|
|
34bdef9c45 | ||
|
|
cad673f8cd | ||
|
|
7c446b222d | ||
|
|
1bd0f8fcf4 | ||
|
|
dd3c261ba2 | ||
|
|
70cc711ec1 | ||
|
|
485f2ee923 | ||
|
|
129be6e476 | ||
|
|
c08b64efb3 | ||
|
|
f4a0f55b13 | ||
|
|
39d32bcb5b | ||
|
|
3351fdbc74 | ||
|
|
7be1f018aa | ||
|
|
437daa368a | ||
|
|
3df09eacf2 | ||
|
|
483dd3435a | ||
|
|
2b0aa03380 | ||
|
|
fc7261b199 | ||
|
|
3200c50b9f | ||
|
|
862a8eab8d | ||
|
|
1bfcc92677 | ||
|
|
80a09b8f36 | ||
|
|
5f7ce4b868 | ||
|
|
412d97fa0c | ||
|
|
57bed98cf1 | ||
|
|
b1d8788506 | ||
|
|
1bd4900981 | ||
|
|
e6812f18a0 | ||
|
|
f604988181 | ||
|
|
150cdfd3ac | ||
|
|
f42b34d6b4 | ||
|
|
166b35bc6c | ||
|
|
121b74fa0c | ||
|
|
5451320350 | ||
|
|
fe45b29ef6 | ||
|
|
4e1aa8aa59 | ||
|
|
fa366eb7a8 | ||
|
|
e086a706ba | ||
|
|
53b8da8198 | ||
|
|
c2c5f71018 | ||
|
|
2bdc849c2b | ||
|
|
7cbe8f5843 | ||
|
|
810df61049 | ||
|
|
5c38101a9e | ||
|
|
b4236b9783 | ||
|
|
980c4699b0 | ||
|
|
463c7b5027 | ||
|
|
7c7230dd35 | ||
|
|
b915aafb5b | ||
|
|
8202ab83fa | ||
|
|
2fe6d14e56 | ||
|
|
7ee285342f | ||
|
|
6fe18ae0ab | ||
|
|
5c4fa213d1 | ||
|
|
1895d8ac9e | ||
|
|
7f5f87ac72 | ||
|
|
0244341ac5 | ||
|
|
ae96d5678b | ||
|
|
a9ebf50b86 | ||
|
|
8d8cbf6e28 | ||
|
|
77e9092108 | ||
|
|
210d7c76e6 | ||
|
|
01ad3f447a | ||
|
|
546948cb8c | ||
|
|
37c20c3f67 | ||
|
|
22daea11e1 | ||
|
|
792aa78aec | ||
|
|
5cf95cfa01 | ||
|
|
fff956304f | ||
|
|
3ae28b3085 | ||
|
|
b5df9dd88e | ||
|
|
b6a01a203a | ||
|
|
990d91360d | ||
|
|
b5c3ac605a | ||
|
|
55865a4f1d | ||
|
|
ff27ad332b | ||
|
|
85bad87c1c | ||
|
|
f7014f14df | ||
|
|
99341bce29 | ||
|
|
bf6291020a | ||
|
|
79829f6209 | ||
|
|
a97487bcec | ||
|
|
892ffc8ce4 | ||
|
|
fbf7f1c3f9 | ||
|
|
3b7e0504e8 | ||
|
|
68bc57ae85 | ||
|
|
f42e5f66fd | ||
|
|
10d31ea0a3 | ||
|
|
e64ebdfaee | ||
|
|
7e15ff930d | ||
|
|
b83610a653 | ||
|
|
16e08384c0 | ||
|
|
9cb14838e8 | ||
|
|
6fe66ad79c | ||
|
|
f78b444ed1 | ||
|
|
9946d15f23 | ||
|
|
b032dcca16 | ||
|
|
01d6ae55a4 | ||
|
|
f1b377bf07 | ||
|
|
03c5208d47 | ||
|
|
3ace9348f6 | ||
|
|
3a14017729 | ||
|
|
e726c0d60b | ||
|
|
98b971b4de | ||
|
|
4ec3d6d064 | ||
|
|
c531d97ed2 | ||
|
|
8c9e416175 | ||
|
|
431f3337d9 | ||
|
|
63ab701685 | ||
|
|
c9b164b983 | ||
|
|
54d32ad910 | ||
|
|
c8140bad19 | ||
|
|
2e5b6bce55 | ||
|
|
5ee178789f | ||
|
|
0efd9fcac0 | ||
|
|
c0a39570c9 | ||
|
|
9ac4b570e6 | ||
|
|
6689827278 | ||
|
|
86a24ebd0f | ||
|
|
d2a7d18067 | ||
|
|
b679672c0e | ||
|
|
90f83db9c9 | ||
|
|
32d74f8623 | ||
|
|
53cc381c76 | ||
|
|
d845736948 | ||
|
|
add107583f | ||
|
|
dd837f7130 | ||
|
|
12ebadbb0f | ||
|
|
e30bc6b6e4 | ||
|
|
9288158226 | ||
|
|
3a55991480 | ||
|
|
9e44596db7 | ||
|
|
e86d811fc0 | ||
|
|
5cff144a22 | ||
|
|
a021adb7fd | ||
|
|
e2a090bbba | ||
|
|
a70c8536f9 | ||
|
|
9aaa152b9a | ||
|
|
a2b8ebf57e | ||
|
|
b3fe47985a | ||
|
|
e52d4fc003 | ||
|
|
3753e3f353 | ||
|
|
979d8e66f2 | ||
|
|
c5b37cc7e7 | ||
|
|
e3989bcc2b | ||
|
|
2f9c512b59 | ||
|
|
43172cf530 | ||
|
|
e518eacbde | ||
|
|
c3b8b279b0 | ||
|
|
0dd4951be7 | ||
|
|
12d06bd727 | ||
|
|
bc52345f05 | ||
|
|
c28a313374 | ||
|
|
c509c8e7e5 | ||
|
|
fb89cef256 | ||
|
|
9ac9fd4fe9 | ||
|
|
dfb89df4f1 | ||
|
|
0e572aea36 | ||
|
|
420cee4ee6 | ||
|
|
403297d967 | ||
|
|
abba254a38 | ||
|
|
048107e378 | ||
|
|
78efe2a960 | ||
|
|
8077091b34 | ||
|
|
683e32cffb | ||
|
|
1c9d76e637 | ||
|
|
98d9901693 | ||
|
|
ee58107caa | ||
|
|
75f358d01e | ||
|
|
01946dd4d6 | ||
|
|
c9e16b2c39 | ||
|
|
77eada7dbd | ||
|
|
f7c97cb1d0 | ||
|
|
f38a2ae14a | ||
|
|
7c22bc74bc | ||
|
|
dfd668d145 | ||
|
|
dbc6dd73f3 | ||
|
|
4765c6fcc5 | ||
|
|
78dd084303 | ||
|
|
cd9fb9b709 | ||
|
|
adcbd879c8 | ||
|
|
227733d195 | ||
|
|
13148728b3 | ||
|
|
8f91ebf194 | ||
|
|
230c635a54 | ||
|
|
e1f930282c | ||
|
|
cb07fe395c | ||
|
|
3917284f71 | ||
|
|
8bfd45c095 | ||
|
|
a001d8cfb7 | ||
|
|
867358ea81 | ||
|
|
62c3e46529 | ||
|
|
8a95ed8ee6 | ||
|
|
20caac1b6e | ||
|
|
48b8c69ba0 | ||
|
|
35d53a0684 | ||
|
|
dbeb252fee | ||
|
|
21614ea891 | ||
|
|
4b38ccef80 | ||
|
|
2d4d18fd75 | ||
|
|
27cd9dde38 | ||
|
|
373da39ac2 | ||
|
|
b7990b7df8 | ||
|
|
4b9047b7d8 | ||
|
|
d226818be3 | ||
|
|
1ee9da79f8 | ||
|
|
070eb6b947 | ||
|
|
cbb0bd5ee7 | ||
|
|
553a25cea7 | ||
|
|
53982272d6 | ||
|
|
a32cf2344f | ||
|
|
934cf32163 | ||
|
|
a17c7b9bbf | ||
|
|
a03df3fad0 | ||
|
|
86cd20dcc3 | ||
|
|
71402b658e | ||
|
|
5d8d8e77f8 | ||
|
|
4dee30ed84 | ||
|
|
025676d6e7 | ||
|
|
aad396ae38 | ||
|
|
c798d131bb | ||
|
|
bf3e024648 | ||
|
|
191f31baa7 | ||
|
|
d3b7903af8 | ||
|
|
99e7d1e161 | ||
|
|
b13166f5d9 | ||
|
|
80fe4458c6 | ||
|
|
791574c26e | ||
|
|
ac61ebf2d5 | ||
|
|
4599e9897d | ||
|
|
cb99ed0a01 | ||
|
|
4864d52966 | ||
|
|
b2d61679fb | ||
|
|
383b3dadd5 | ||
|
|
c65c259123 | ||
|
|
e7e2730929 | ||
|
|
bb9615eed0 | ||
|
|
18877bf80e | ||
|
|
778b784eb6 | ||
|
|
5ff900f7ec | ||
|
|
ba31424604 | ||
|
|
1782111d45 | ||
|
|
1fa63300aa | ||
|
|
b42c918973 | ||
|
|
f12262ea96 | ||
|
|
334cf45d6d | ||
|
|
b7bb72294a | ||
|
|
64ff204371 | ||
|
|
282367c6d5 | ||
|
|
36c33a5889 | ||
|
|
5ee7e81ff9 | ||
|
|
f4859444dd | ||
|
|
73c7994cd1 | ||
|
|
0c74090953 | ||
|
|
f60d54eae4 | ||
|
|
31bc015cdd | ||
|
|
b028ad3604 | ||
|
|
d2e4e35c37 | ||
|
|
1f37200bb6 | ||
|
|
77178daad3 | ||
|
|
1648f161d9 | ||
|
|
9fa6cea69b | ||
|
|
66b827e502 | ||
|
|
7755a902dd | ||
|
|
d25b73f47d | ||
|
|
ac2969c3f8 | ||
|
|
ee38b2ef03 | ||
|
|
0f70e04e6e | ||
|
|
9fc1e7272e | ||
|
|
0d4d0b8a37 | ||
|
|
fcd2c989a2 | ||
|
|
e0d0d6c455 | ||
|
|
ce1a961b99 | ||
|
|
c71a08a9d9 | ||
|
|
17bfcea65a | ||
|
|
5e8959bab1 | ||
|
|
9924dc0f92 | ||
|
|
7388c036d7 | ||
|
|
ad4512801f | ||
|
|
409b9af398 | ||
|
|
7cc8fd7e87 | ||
|
|
42c8105f13 | ||
|
|
9a71cc5b4e | ||
|
|
c543b7469d | ||
|
|
7caac3265a | ||
|
|
5d68d5a246 | ||
|
|
7187f87eae | ||
|
|
fb81f3e77e | ||
|
|
0ae49ed098 | ||
|
|
b8e5aaf754 | ||
|
|
aa4820c3b7 | ||
|
|
5d79d6e134 | ||
|
|
fb1455a17b | ||
|
|
c668eeba0f | ||
|
|
62421ee49d | ||
|
|
e791f29ce1 | ||
|
|
06947cc453 | ||
|
|
8c97474524 | ||
|
|
77a8568b28 | ||
|
|
e2dadbd7fe | ||
|
|
17b668a115 | ||
|
|
a30c2b6a75 | ||
|
|
2660eebec2 | ||
|
|
f415664b6d | ||
|
|
5092b29312 | ||
|
|
d5be901bc2 | ||
|
|
5462eddfdb | ||
|
|
fef51f12c6 | ||
|
|
fdb3679cf5 | ||
|
|
11beb37c50 | ||
|
|
5cd17730b1 | ||
|
|
cb192056f8 | ||
|
|
892f96e305 | ||
|
|
13ef58a5bb | ||
|
|
2bf6509e1d | ||
|
|
a45d5a98dd | ||
|
|
a31714f8a4 | ||
|
|
23d2a806f0 | ||
|
|
c20b2330ab | ||
|
|
8613551aec | ||
|
|
2ab01dadc0 | ||
|
|
790636c8cd | ||
|
|
23938830f7 | ||
|
|
674b87057a | ||
|
|
83d9248ec8 | ||
|
|
f9d27e4a67 | ||
|
|
2683803ef3 | ||
|
|
dd86d7a5ed | ||
|
|
1246a81d39 | ||
|
|
8ab7278db2 | ||
|
|
db099e7722 | ||
|
|
fcc01bc37e | ||
|
|
a18dacf5f2 | ||
|
|
77f9cae50b | ||
|
|
3610bbf21b | ||
|
|
d5e3be9a55 | ||
|
|
80b369d6d5 | ||
|
|
d29eb84010 | ||
|
|
381ce535bf | ||
|
|
2e20bb0639 | ||
|
|
56cd24797e | ||
|
|
431ca99c23 | ||
|
|
6ced2ff293 | ||
|
|
31055bb303 | ||
|
|
24a53e39dd | ||
|
|
2ab113b695 | ||
|
|
9a0481a750 | ||
|
|
09035eb4c4 | ||
|
|
1adf268e71 | ||
|
|
23f57ad5a7 | ||
|
|
d9b15cf69e | ||
|
|
dbfe12a993 | ||
|
|
2b32dfd99d | ||
|
|
679de40780 | ||
|
|
66f15fdd37 | ||
|
|
038f0e45b1 | ||
|
|
033bfcc804 | ||
|
|
fa87c08a29 | ||
|
|
dfb799739a | ||
|
|
1193f7ed22 | ||
|
|
7530c21a9f | ||
|
|
a120614617 | ||
|
|
0311f0db38 | ||
|
|
547b683e61 | ||
|
|
ff1d943a69 | ||
|
|
15a5c89e86 | ||
|
|
03b974ee3f | ||
|
|
f145605c63 | ||
|
|
29230d0316 | ||
|
|
57fc49ddc2 | ||
|
|
5ac6853fed | ||
|
|
b870214cca | ||
|
|
55074b925f | ||
|
|
958424ce59 | ||
|
|
d04fc289ac | ||
|
|
e14edf134d | ||
|
|
dbb127447f | ||
|
|
dc94fc39ec | ||
|
|
6db9a7cb12 | ||
|
|
1f39386616 | ||
|
|
25aef945d1 | ||
|
|
c9aa43afe0 | ||
|
|
913e177f6f | ||
|
|
ae431aec12 | ||
|
|
8ac15048cd | ||
|
|
a1cfe87f1e | ||
|
|
c130396d4e | ||
|
|
bc2e7cf317 | ||
|
|
7ace1d652d | ||
|
|
26effd1def | ||
|
|
5f6824e5dd | ||
|
|
4589bdd31f | ||
|
|
72e0b49e0b | ||
|
|
3caa45d860 | ||
|
|
7c069f14f8 | ||
|
|
552885dbd3 | ||
|
|
6efeb1471c | ||
|
|
01f062d2ba | ||
|
|
2a42c463d2 | ||
|
|
182843edf6 | ||
|
|
9a9d36e9d9 | ||
|
|
7d5249eea6 | ||
|
|
f7910c41c3 | ||
|
|
3973f4f952 | ||
|
|
8a19769a47 | ||
|
|
c0ee593c10 | ||
|
|
c806451b8a | ||
|
|
00e5ff1964 | ||
|
|
432aec62a9 | ||
|
|
c8ec7e5191 | ||
|
|
a0d2b96de6 | ||
|
|
2c202b82d7 | ||
|
|
a42dc08756 | ||
|
|
48f58110fe | ||
|
|
7b3724972b | ||
|
|
9ca2a16218 | ||
|
|
f1e8400abf | ||
|
|
11e0ffa90a | ||
|
|
2ee4326a4d | ||
|
|
226e72ac18 | ||
|
|
65c78b8f3f | ||
|
|
6137c7ca06 | ||
|
|
5bebf11b37 | ||
|
|
68161d2714 | ||
|
|
a6473cb826 | ||
|
|
0084c6f96a | ||
|
|
a87825dbee | ||
|
|
3566154cd0 | ||
|
|
92d69e320f | ||
|
|
08a190ef5b | ||
|
|
98339ee5d8 | ||
|
|
fa387fd758 | ||
|
|
54979f2fc4 | ||
|
|
538e90f23a | ||
|
|
d9107bcac6 | ||
|
|
3f3a0b9140 | ||
|
|
e1347e434e | ||
|
|
7657faa9c3 | ||
|
|
28ef765913 | ||
|
|
d2f59391a2 | ||
|
|
df90bdb350 | ||
|
|
c416c77d7a | ||
|
|
ce05a720d1 | ||
|
|
6c19a440f5 | ||
|
|
f4612fdb5d | ||
|
|
04b9a0b09e | ||
|
|
f93c438067 | ||
|
|
e1d608443a | ||
|
|
9233c3a898 | ||
|
|
dfa514334b | ||
|
|
5810a96e62 | ||
|
|
70473a80af | ||
|
|
525fd30cb2 | ||
|
|
5212cd4dcd | ||
|
|
e95bde62a2 | ||
|
|
4fe73cf6ad | ||
|
|
78b2835da4 | ||
|
|
f9a49efae9 | ||
|
|
b9ddc9e678 | ||
|
|
dc459c84a3 | ||
|
|
1d26239809 | ||
|
|
5ca233779d | ||
|
|
e51b4897a3 | ||
|
|
81f283e56f | ||
|
|
ccdd2fd2ca | ||
|
|
69f11a29e1 | ||
|
|
cf494f3238 | ||
|
|
d5895c635a | ||
|
|
2ac9873613 | ||
|
|
eb59e76cde | ||
|
|
d9db845b43 | ||
|
|
e55327b064 | ||
|
|
bdd5a4e053 | ||
|
|
ac2e2c9a42 | ||
|
|
76f9d49e24 | ||
|
|
6ec8ab95fc | ||
|
|
9c98625610 | ||
|
|
f270cde47d | ||
|
|
9de7efd072 | ||
|
|
7b81d317a0 | ||
|
|
876f975aa2 | ||
|
|
3c5815ac0f | ||
|
|
678ae2d684 | ||
|
|
e4f8f44fb0 | ||
|
|
49566d29f8 | ||
|
|
7f4ee7b20a | ||
|
|
32526a8c16 | ||
|
|
71a7f72ab9 | ||
|
|
4d0824f4a4 | ||
|
|
d56dd40d06 | ||
|
|
6aafd6dc3a | ||
|
|
011b512f28 | ||
|
|
aa2d17e489 | ||
|
|
0eee2293dc | ||
|
|
a2f35d2bda | ||
|
|
58f58d9ee8 | ||
|
|
412bb349ac | ||
|
|
652f15f893 | ||
|
|
8512ebb923 | ||
|
|
f0ac173ec8 | ||
|
|
bef0d47924 | ||
|
|
cba0d59021 | ||
|
|
7d3afcab94 | ||
|
|
5f1cda07e7 | ||
|
|
e11beade4b | ||
|
|
6a1e089b73 | ||
|
|
0aa98ac2da | ||
|
|
f9ef38cc7a | ||
|
|
a3a215a1ba | ||
|
|
d3ee322d7c | ||
|
|
7ec20e7752 | ||
|
|
08dfb13dbf | ||
|
|
6a5cddd907 | ||
|
|
dc5078306d | ||
|
|
1bc032853c | ||
|
|
e562e4e7b9 | ||
|
|
0ffffa9029 | ||
|
|
0f2303e8d5 | ||
|
|
31f7f8149e | ||
|
|
fe1f57c23f | ||
|
|
29a0b010da | ||
|
|
621e1163f8 | ||
|
|
17d64cfcbe | ||
|
|
7379d2135d | ||
|
|
c55fd06b99 | ||
|
|
d81727a08c | ||
|
|
b582e1592a | ||
|
|
dd8533a320 | ||
|
|
d72a8cbf89 | ||
|
|
fe0876ded6 | ||
|
|
fa15763c5d | ||
|
|
205215d409 | ||
|
|
076bfcde87 | ||
|
|
10510484b5 | ||
|
|
e1dea5b4d3 | ||
|
|
891f8d00cf | ||
|
|
0d409f0fe3 | ||
|
|
4e0c8982c9 | ||
|
|
a741c66c97 | ||
|
|
3e6a7cbdf5 | ||
|
|
5d34aa0afe | ||
|
|
979ae94698 | ||
|
|
8d7b85b26a | ||
|
|
686977a986 | ||
|
|
9c6c782146 | ||
|
|
ca9539b5b6 | ||
|
|
ff25be8839 | ||
|
|
d1ab1b59be | ||
|
|
05bc1865a6 | ||
|
|
6e6e0275ad | ||
|
|
ec3c5b2ca2 | ||
|
|
5289d569b0 | ||
|
|
6f873ff6b5 | ||
|
|
467cbe972c | ||
|
|
bfd1bfe9f0 | ||
|
|
3404a6c699 | ||
|
|
17a4b5155e | ||
|
|
d406e2ed22 | ||
|
|
0bfc9935b2 | ||
|
|
64c6cbe303 | ||
|
|
2245db3e80 | ||
|
|
6f19a50c98 | ||
|
|
c7ce9598a8 | ||
|
|
afcdccf783 | ||
|
|
1bf12842ca | ||
|
|
da8fbee256 | ||
|
|
4021f26e76 | ||
|
|
8eab8438cf | ||
|
|
1b4096b01d | ||
|
|
54caa6e438 | ||
|
|
486eb149f2 | ||
|
|
faa034a205 | ||
|
|
2cd3ebc7a8 | ||
|
|
7e3af6c235 | ||
|
|
dd4de16d1d | ||
|
|
ba8577fa5f | ||
|
|
6192319f8c | ||
|
|
fed368d553 | ||
|
|
20c885418e | ||
|
|
9318ee30bd | ||
|
|
8b6c9574df | ||
|
|
313148136a | ||
|
|
6e1fdc77ae | ||
|
|
2a9582ebb1 | ||
|
|
dd1cd46719 | ||
|
|
9961d9e54d | ||
|
|
7eb12110d1 | ||
|
|
3d62744601 | ||
|
|
17af417235 | ||
|
|
df9d314361 | ||
|
|
610e0c984a | ||
|
|
3688fca126 | ||
|
|
9bc89c784f | ||
|
|
79682f5d52 | ||
|
|
c206ac0335 | ||
|
|
34840175f3 | ||
|
|
6312457425 | ||
|
|
f71e664952 | ||
|
|
80d559f17e | ||
|
|
772aedc263 | ||
|
|
45d7c124c8 | ||
|
|
73abb20b3d | ||
|
|
0baf104a75 | ||
|
|
302d51cdfd | ||
|
|
d3cbfd5467 | ||
|
|
9e3e7e1820 | ||
|
|
18893bf6cd | ||
|
|
f53161d6f5 | ||
|
|
4c9a571106 | ||
|
|
365edcad16 | ||
|
|
ae9047a708 | ||
|
|
9c0e58df8d | ||
|
|
ee34f11c29 | ||
|
|
6ca6d88bff | ||
|
|
65a397fb63 | ||
|
|
0a669077fb | ||
|
|
451688a12e | ||
|
|
d181d89dd2 | ||
|
|
ac14b0d73b | ||
|
|
0f42c65792 | ||
|
|
37b3e980dc | ||
|
|
eb49e011e2 | ||
|
|
e0a73f72ee | ||
|
|
e217ab28c5 | ||
|
|
ca583865ea | ||
|
|
5e7efde311 | ||
|
|
2c7c13420b | ||
|
|
ac4fc3e54e | ||
|
|
46db36a05e | ||
|
|
3d073be990 | ||
|
|
1bc49fe450 | ||
|
|
1f7fe9abcc | ||
|
|
5217abf57a | ||
|
|
2ecbde891a | ||
|
|
bf7fc66646 | ||
|
|
5a94b38e2f | ||
|
|
1bc55f5937 | ||
|
|
04c9542f94 | ||
|
|
17e739f68a | ||
|
|
4f5515fde3 | ||
|
|
ae3ba129ea | ||
|
|
6b92a0fff7 | ||
|
|
d859bb8e67 | ||
|
|
f12bbf71ed | ||
|
|
b723beb545 | ||
|
|
47daaaf14f | ||
|
|
9ba5bae34d | ||
|
|
dbfa2d7994 | ||
|
|
8134f86d1f | ||
|
|
5c60b09bf4 | ||
|
|
20a19d67d0 | ||
|
|
311a2f6023 | ||
|
|
59a3cf93e6 | ||
|
|
a42f095cef | ||
|
|
a29340523f | ||
|
|
5ad7a7c014 | ||
|
|
c6fa7e4aad | ||
|
|
d4b248fbe3 | ||
|
|
48881d081a | ||
|
|
331024414e | ||
|
|
9d0c5349bb | ||
|
|
dc40d8afac | ||
|
|
005877b4b8 | ||
|
|
774d21747a | ||
|
|
12e5b39c05 | ||
|
|
4d5e452ece | ||
|
|
1ba3ecbef3 | ||
|
|
db6695cb02 | ||
|
|
b3f5e039f2 | ||
|
|
c3e17fb185 | ||
|
|
f7ae7fe43a | ||
|
|
e07822350e | ||
|
|
07439ff99c | ||
|
|
f111c245c1 | ||
|
|
c3502da4a0 | ||
|
|
4012108d48 | ||
|
|
4a0605e09b | ||
|
|
250380d73e | ||
|
|
b30f5d782d | ||
|
|
b00cd9b557 | ||
|
|
e11f8f646b | ||
|
|
92b1de8cf8 | ||
|
|
bbafe53a2b | ||
|
|
e239fd970f | ||
|
|
7fa4515c28 | ||
|
|
b40eb0a454 | ||
|
|
5e3e9ddb8e | ||
|
|
a9a5284a67 | ||
|
|
afe504dbbf | ||
|
|
0c484ddcf7 | ||
|
|
8d0e80620a | ||
|
|
1d28506b09 | ||
|
|
1b33dbe2ae | ||
|
|
80654c059d | ||
|
|
999c548e6e | ||
|
|
e42913ae8a | ||
|
|
ee07cbecba | ||
|
|
fffaa9bced | ||
|
|
6195b2c99d | ||
|
|
06aafc96c9 | ||
|
|
2dc0727e36 | ||
|
|
a219feaa60 | ||
|
|
f3a09da340 | ||
|
|
946e345a3f | ||
|
|
6cb8d11b22 | ||
|
|
fdcf9c5327 | ||
|
|
45c714cbb5 | ||
|
|
7352a309a0 | ||
|
|
b297fe6f59 | ||
|
|
e575212c49 | ||
|
|
c52dc10c9e | ||
|
|
d35c913249 | ||
|
|
9bac59b952 | ||
|
|
5016253922 | ||
|
|
03893071fc | ||
|
|
d3dc94c04b | ||
|
|
af0feabb6a | ||
|
|
81ab0a414f | ||
|
|
ecd6ca0172 | ||
|
|
db7ee192f7 | ||
|
|
2ec0b601fa | ||
|
|
79feb6d5d2 | ||
|
|
8013b760e3 | ||
|
|
a29b8e5b36 | ||
|
|
9ef487a7a5 | ||
|
|
563fa46ba4 | ||
|
|
7865c06863 | ||
|
|
3d53b9244d | ||
|
|
f2afa4dd50 | ||
|
|
893ecec55e | ||
|
|
401584dbd8 | ||
|
|
b234b0bded | ||
|
|
b9b2c6a013 | ||
|
|
1d2efa0d25 | ||
|
|
93ec092eaf | ||
|
|
29ae492983 | ||
|
|
b9f6a59a20 | ||
|
|
d74551216f | ||
|
|
d4302ae51b | ||
|
|
9d5fb0b201 | ||
|
|
e0a5fe4002 | ||
|
|
f9d9a0a4bd | ||
|
|
78f0c7b119 | ||
|
|
c6d8343de2 | ||
|
|
0ccd11e587 | ||
|
|
b486711d68 | ||
|
|
2eb4c5e960 | ||
|
|
85aa740c98 | ||
|
|
6415848383 | ||
|
|
beb9460538 | ||
|
|
c030770be7 | ||
|
|
0180342dff | ||
|
|
b97748d3dc | ||
|
|
9d4977db00 | ||
|
|
f095284faa | ||
|
|
401c2f42f9 | ||
|
|
eb0348d47c | ||
|
|
1f46240ba9 | ||
|
|
14870726e0 | ||
|
|
c7d6a2eecb | ||
|
|
ce61eb2174 | ||
|
|
f3df21ef0a | ||
|
|
5eb554e008 | ||
|
|
e5e7c3fad3 | ||
|
|
2a8b9ab75e | ||
|
|
c8f0ffb42f | ||
|
|
b3e68b96cf | ||
|
|
ae7a550a09 | ||
|
|
e069bbb800 | ||
|
|
17ff6be6a9 | ||
|
|
d42489c67a | ||
|
|
3ea72e5d21 | ||
|
|
762854ad7a | ||
|
|
10465066ee | ||
|
|
0cf9f51816 | ||
|
|
3d5e2340ca | ||
|
|
e2047afa42 | ||
|
|
231b39d2dc | ||
|
|
dddce30368 | ||
|
|
e0e4ba2bd7 | ||
|
|
e0eadb6b76 | ||
|
|
483e5dfbea | ||
|
|
8aa9d8213d | ||
|
|
a74f71c935 | ||
|
|
87b81e53f0 | ||
|
|
a2816e31c3 | ||
|
|
f78af9f27b | ||
|
|
98138a0a60 | ||
|
|
e639b6303e | ||
|
|
99fb3ebe00 | ||
|
|
5829840409 | ||
|
|
4699ab5500 | ||
|
|
69fc7f39b7 | ||
|
|
510a962a52 | ||
|
|
570fc3cfb2 | ||
|
|
5d211f2fa6 | ||
|
|
dcb127c14d | ||
|
|
fba87de064 | ||
|
|
576f8cba44 | ||
|
|
b9f9429542 | ||
|
|
bf0df9f3c3 | ||
|
|
1d458f2782 | ||
|
|
5ca4b4a884 | ||
|
|
5935052ead | ||
|
|
f3f2ad9144 | ||
|
|
9d1edc4554 | ||
|
|
5143b8a492 | ||
|
|
7c67f40fc4 | ||
|
|
167b600135 | ||
|
|
6c465e25d3 | ||
|
|
c183d06ed1 | ||
|
|
574731b853 | ||
|
|
94568a4ec8 | ||
|
|
b22c0e5b6d | ||
|
|
ab3347d25d | ||
|
|
66872de8e5 | ||
|
|
f6d4402fdc | ||
|
|
9f66ccb5f3 | ||
|
|
b339330592 | ||
|
|
56acd2953b | ||
|
|
6f8e13297e | ||
|
|
e9a9144098 | ||
|
|
d1905dbee8 | ||
|
|
adc88f01b7 | ||
|
|
507554b8e8 | ||
|
|
4795133daf | ||
|
|
c1c9075962 | ||
|
|
a691e9f744 | ||
|
|
8969eed506 | ||
|
|
be83095edf | ||
|
|
5c7783305a | ||
|
|
d60806bfa6 | ||
|
|
32febcb892 | ||
|
|
6c594b6f5f | ||
|
|
67d46432ed | ||
|
|
adf4166caa | ||
|
|
d9e7984279 | ||
|
|
e5b9900d3b | ||
|
|
fc3f1431b2 | ||
|
|
c8bf2f4cb1 | ||
|
|
d16555ec4b | ||
|
|
3c9415b1c2 | ||
|
|
aa45670d87 | ||
|
|
e6d801a594 | ||
|
|
0aec2be4dd | ||
|
|
c86b618aaa | ||
|
|
dffd2deb53 | ||
|
|
8ff48b371e | ||
|
|
6de66b87cb | ||
|
|
45680a562e |
46
.asf.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
github:
|
||||
description: Apache Cordova Android
|
||||
homepage: https://cordova.apache.org/
|
||||
|
||||
labels:
|
||||
- cordova
|
||||
- cordova-platform
|
||||
- android
|
||||
- java
|
||||
- mobile
|
||||
- javascript
|
||||
- nodejs
|
||||
- hacktoberfest
|
||||
|
||||
features:
|
||||
wiki: false
|
||||
issues: true
|
||||
projects: true
|
||||
|
||||
enabled_merge_buttons:
|
||||
squash: true
|
||||
merge: false
|
||||
rebase: false
|
||||
|
||||
notifications:
|
||||
commits: commits@cordova.apache.org
|
||||
issues: issues@cordova.apache.org
|
||||
pullrequests_status: issues@cordova.apache.org
|
||||
pullrequests_comment: issues@cordova.apache.org
|
||||
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
templates/project/assets/www/cordova.js
|
||||
test/android/app
|
||||
test/androidx/app
|
||||
27
.eslintrc.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
extends: '@cordova/eslint-config/node'
|
||||
|
||||
overrides:
|
||||
- files: [spec/**/*.js]
|
||||
extends: '@cordova/eslint-config/node-tests'
|
||||
rules:
|
||||
prefer-promise-reject-errors: off
|
||||
|
||||
- files: [cordova-js-src/**/*.js]
|
||||
extends: '@cordova/eslint-config/browser'
|
||||
94
.gitattributes
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
* text eol=lf
|
||||
|
||||
# source code
|
||||
*.php text
|
||||
*.css text
|
||||
*.sass text
|
||||
*.scss text
|
||||
*.less text
|
||||
*.styl text
|
||||
*.js text
|
||||
*.coffee text
|
||||
*.json text
|
||||
*.htm text
|
||||
*.html text
|
||||
*.xml text
|
||||
*.svg text
|
||||
*.txt text
|
||||
*.ini text
|
||||
*.inc text
|
||||
*.pl text
|
||||
*.rb text
|
||||
*.py text
|
||||
*.scm text
|
||||
*.sql text
|
||||
*.sh text
|
||||
*.bat text
|
||||
|
||||
# templates
|
||||
*.ejs text
|
||||
*.hbt text
|
||||
*.jade text
|
||||
*.haml text
|
||||
*.hbs text
|
||||
*.dot text
|
||||
*.tmpl text
|
||||
*.phtml text
|
||||
|
||||
# server config
|
||||
.htaccess text
|
||||
|
||||
# git config
|
||||
.gitattributes text
|
||||
.gitignore text
|
||||
.gitconfig text
|
||||
|
||||
# code analysis config
|
||||
.jshintrc text
|
||||
.jscsrc text
|
||||
.jshintignore text
|
||||
.csslintrc text
|
||||
|
||||
# misc config
|
||||
*.yaml text
|
||||
*.yml text
|
||||
.editorconfig text
|
||||
|
||||
# build config
|
||||
*.npmignore text
|
||||
*.bowerrc text
|
||||
|
||||
# Heroku
|
||||
Procfile text
|
||||
.slugignore text
|
||||
|
||||
# Documentation
|
||||
*.md text
|
||||
LICENSE text
|
||||
AUTHORS text
|
||||
|
||||
|
||||
#
|
||||
## These files are binary and should be left untouched
|
||||
#
|
||||
|
||||
# (binary is a macro for -text -diff)
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.mov binary
|
||||
*.mp4 binary
|
||||
*.mp3 binary
|
||||
*.flv binary
|
||||
*.fla binary
|
||||
*.swf binary
|
||||
*.gz binary
|
||||
*.zip binary
|
||||
*.7z binary
|
||||
*.ttf binary
|
||||
*.eot binary
|
||||
*.woff binary
|
||||
*.pyc binary
|
||||
*.pdf binary
|
||||
42
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
Please have a look at the issue templates you get when you click "New issue" in the GitHub UI.
|
||||
We very much prefer issues created by using one of these templates.
|
||||
-->
|
||||
|
||||
### Issue Type
|
||||
<!-- Please check the boxes by putting an x in the [ ] like so: [x] -->
|
||||
|
||||
- [ ] Bug Report
|
||||
- [ ] Feature Request
|
||||
- [ ] Support Question
|
||||
|
||||
## Description
|
||||
|
||||
## Information
|
||||
<!-- Include all relevant information that might help understand and reproduce the problem -->
|
||||
|
||||
### Command or Code
|
||||
<!-- What command or code is needed to reproduce the problem? -->
|
||||
|
||||
### Environment, Platform, Device
|
||||
<!-- In what environment, on what platform or on which device are you experiencing the issue? -->
|
||||
|
||||
|
||||
|
||||
### Version information
|
||||
<!--
|
||||
What are relevant versions you are using?
|
||||
For example:
|
||||
Cordova: Cordova CLI, Cordova Platforms, Cordova Plugins
|
||||
Other Frameworks: Ionic Framework and CLI version
|
||||
Operating System, Android Studio, Xcode etc.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## Checklist
|
||||
<!-- Please check the boxes by putting an `x` in the `[ ]` like so: `[x]` -->
|
||||
|
||||
- [ ] I searched for already existing GitHub issues about this
|
||||
- [ ] I updated all Cordova tooling to their most recent version
|
||||
- [ ] I included all the necessary information above
|
||||
50
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: If something isn't working as expected.
|
||||
|
||||
---
|
||||
|
||||
# Bug Report
|
||||
|
||||
## Problem
|
||||
|
||||
### What is expected to happen?
|
||||
|
||||
|
||||
|
||||
### What does actually happen?
|
||||
|
||||
|
||||
|
||||
## Information
|
||||
<!-- Include all relevant information that might help understand and reproduce the problem -->
|
||||
|
||||
|
||||
|
||||
### Command or Code
|
||||
<!-- What command or code is needed to reproduce the problem? -->
|
||||
|
||||
|
||||
|
||||
### Environment, Platform, Device
|
||||
<!-- In what environment, on what platform or on which device are you experiencing the issue? -->
|
||||
|
||||
|
||||
|
||||
### Version information
|
||||
<!--
|
||||
What are relevant versions you are using?
|
||||
For example:
|
||||
Cordova: Cordova CLI, Cordova Platforms, Cordova Plugins
|
||||
Other Frameworks: Ionic Framework and CLI version
|
||||
Operating System, Android Studio, Xcode etc.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## Checklist
|
||||
<!-- Please check the boxes by putting an x in the [ ] like so: [x] -->
|
||||
|
||||
- [ ] I searched for existing GitHub issues
|
||||
- [ ] I updated all Cordova tooling to most recent version
|
||||
- [ ] I included all the necessary information above
|
||||
29
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: 🚀 Feature Request
|
||||
about: A suggestion for a new functionality
|
||||
|
||||
---
|
||||
|
||||
# Feature Request
|
||||
|
||||
## Motivation Behind Feature
|
||||
<!-- Why should this feature be implemented? What problem does it solve? -->
|
||||
|
||||
|
||||
|
||||
## Feature Description
|
||||
<!--
|
||||
Describe your feature request in detail
|
||||
Please provide any code examples or screenshots of what this feature would look like
|
||||
Are there any drawbacks? Will this break anything for existing users?
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## Alternatives or Workarounds
|
||||
<!--
|
||||
Describe alternatives or workarounds you are currently using
|
||||
Are there ways to do this with existing functionality?
|
||||
-->
|
||||
|
||||
|
||||
27
.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: 💬 Support Question
|
||||
about: If you have a question, please check out our Slack or StackOverflow!
|
||||
|
||||
---
|
||||
|
||||
<!------------^ Click "Preview" for a nicer view! -->
|
||||
|
||||
Apache Cordova uses GitHub Issues as a feature request and bug tracker _only_.
|
||||
For usage and support questions, please check out the resources below. Thanks!
|
||||
|
||||
---
|
||||
|
||||
You can get answers to your usage and support questions about **Apache Cordova** on:
|
||||
|
||||
* Slack Community Chat: https://cordova.slack.com (you can sign-up at http://slack.cordova.io/)
|
||||
* StackOverflow: https://stackoverflow.com/questions/tagged/cordova using the tag `cordova`
|
||||
|
||||
---
|
||||
|
||||
If you are using a tool that uses Cordova internally, like e.g. Ionic, check their support channels:
|
||||
|
||||
* **Ionic Framework**
|
||||
* [Ionic Community Forum](https://forum.ionicframework.com/)
|
||||
* [Ionic Worldwide Slack](https://ionicworldwide.herokuapp.com/)
|
||||
* **PhoneGap**
|
||||
* [PhoneGap Developer Community](https://forums.adobe.com/community/phonegap)
|
||||
35
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Please make sure the checklist boxes are all checked before submitting the PR. The checklist is intended as a quick reference, for complete details please see our Contributor Guidelines:
|
||||
|
||||
http://cordova.apache.org/contribute/contribute_guidelines.html
|
||||
|
||||
Thanks!
|
||||
-->
|
||||
|
||||
### Platforms affected
|
||||
|
||||
|
||||
|
||||
### Motivation and Context
|
||||
<!-- Why is this change required? What problem does it solve? -->
|
||||
<!-- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
|
||||
|
||||
### Description
|
||||
<!-- Describe your changes in detail -->
|
||||
|
||||
|
||||
|
||||
### Testing
|
||||
<!-- Please describe in detail how you tested your changes. -->
|
||||
|
||||
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] I've run the tests to see all new and existing tests pass
|
||||
- [ ] I added automated test coverage as appropriate for this change
|
||||
- [ ] Commit is prefixed with `(platform)` if this change only applies to one platform (e.g. `(android)`)
|
||||
- [ ] If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct [keyword to close issues using keywords](https://help.github.com/articles/closing-issues-using-keywords/))
|
||||
- [ ] I've updated the documentation if necessary
|
||||
61
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
name: Node CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: NodeJS ${{ matrix.node-version }} on ${{ matrix.os }}
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Environment Information
|
||||
run: |
|
||||
node --version
|
||||
npm --version
|
||||
gradle --version
|
||||
|
||||
- name: npm install and test
|
||||
run: |
|
||||
npm i
|
||||
npm t
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- uses: codecov/codecov-action@v1
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
65
.gitignore
vendored
@@ -1,20 +1,57 @@
|
||||
.DS_Store
|
||||
.gradle
|
||||
.metadata
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*.class
|
||||
*.jar
|
||||
default.properties
|
||||
gen
|
||||
assets/www/cordova.js
|
||||
local.properties
|
||||
framework/proguard.cfg
|
||||
framework/cordova.jar
|
||||
framework/cordova-*.jar
|
||||
framework/phonegap-*.jar
|
||||
framework/bin
|
||||
framework/test/org/apache/cordova/*.class
|
||||
framework/assets/www/.DS_Store
|
||||
framework/assets/www/cordova-*.js
|
||||
framework/assets/www/phonegap-*.js
|
||||
proguard.cfg
|
||||
proguard-project.txt
|
||||
example
|
||||
./test
|
||||
tmp
|
||||
*.tmp
|
||||
test/libs/*.jar
|
||||
bin/node_modules
|
||||
/coverage
|
||||
/framework/lib
|
||||
/framework/build
|
||||
/framework/bin
|
||||
/framework/assets/www/.DS_Store
|
||||
/framework/assets/www/cordova-*.js
|
||||
/framework/assets/www/phonegap-*.js
|
||||
/framework/libs
|
||||
/framework/javadoc-public
|
||||
/framework/javadoc-private
|
||||
|
||||
**/assets/www/cordova.js
|
||||
|
||||
/test/.externalNativeBuild
|
||||
|
||||
/test/androidx/gradle
|
||||
/test/androidx/gradlew
|
||||
/test/androidx/gradlew.bat
|
||||
/test/androidx/cdv-gradle-config.json
|
||||
|
||||
/test/assets/www/.tmp*
|
||||
/test/assets/www/cordova.js
|
||||
/test/bin
|
||||
/test/build
|
||||
/test/captures
|
||||
/test/libs
|
||||
tmp/**
|
||||
tmp/**/*
|
||||
!/spec/fixtures/org.test.plugins.dummyplugin/src/android/TestLib.jar
|
||||
# IntelliJ IDEA files
|
||||
**/.idea/**/*
|
||||
*.iml
|
||||
npm-debug.log
|
||||
node_modules/
|
||||
coverage/
|
||||
.nyc_output/
|
||||
# Eclipse Buildship files
|
||||
.project
|
||||
.settings
|
||||
.classpath
|
||||
|
||||
6
.npmignore
Normal file
@@ -0,0 +1,6 @@
|
||||
.*
|
||||
coverage
|
||||
test
|
||||
spec
|
||||
framework/build
|
||||
cordova-js-src
|
||||
8
.ratignore
Normal file
@@ -0,0 +1,8 @@
|
||||
*.properties
|
||||
templates
|
||||
gen
|
||||
proguard-project.txt
|
||||
spec
|
||||
framework/build
|
||||
ic_launcher.png
|
||||
build
|
||||
8
.reviewboardrc
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# Settings for post-review (used for uploading diffs to reviews.apache.org).
|
||||
#
|
||||
GUESS_FIELDS = True
|
||||
OPEN_BROWSER = True
|
||||
TARGET_GROUPS = 'cordova'
|
||||
REVIEWBOARD_URL = 'https://reviews.apache.org'
|
||||
|
||||
37
CONTRIBUTING.md
Normal file
@@ -0,0 +1,37 @@
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
# Contributing to Apache Cordova
|
||||
|
||||
Anyone can contribute to Cordova. And we need your contributions.
|
||||
|
||||
There are multiple ways to contribute: report bugs, improve the docs, and
|
||||
contribute code.
|
||||
|
||||
For instructions on this, start with the
|
||||
[contribution overview](http://cordova.apache.org/contribute/).
|
||||
|
||||
The details are explained there, but the important items are:
|
||||
- Check for Github issues that corresponds to your contribution and link or create them if necessary.
|
||||
- Run the tests so your patch doesn't break existing functionality.
|
||||
|
||||
We look forward to your contributions!
|
||||
|
||||
4
LICENSE
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright 2015-2020 Apache Cordova
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -199,4 +199,4 @@
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
limitations under the License.
|
||||
|
||||
6
NOTICE
@@ -1,5 +1,5 @@
|
||||
Apache Cordova
|
||||
Copyright 2012 The Apache Software Foundation
|
||||
Copyright 2015-2020 The Apache Software Foundation
|
||||
|
||||
This product includes software developed by
|
||||
The Apache Software Foundation (http://www.apache.org)
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
137
README.md
Executable file → Normal file
@@ -1,114 +1,49 @@
|
||||
Cordova Android
|
||||
===
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
Cordova Android is an Android application library that allows for Cordova based projects to be built for the Android Platform. Cordova based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
|
||||
# Cordova Android
|
||||
|
||||
Apache Cordova is an effort undergoing incubation at The Apache
|
||||
Software Foundation (ASF), sponsored by the Apache Incubator project.
|
||||
Incubation is required of all newly accepted projects until a further
|
||||
review indicates that the infrastructure, communications, and decision
|
||||
making process have stabilized in a manner consistent with other
|
||||
successful ASF projects. While incubation status is not necessarily
|
||||
a reflection of the completeness or stability of the code, it does
|
||||
indicate that the project has yet to be fully endorsed by the ASF.
|
||||
[](https://nodei.co/npm/cordova-android/)
|
||||
|
||||
Requires
|
||||
---
|
||||
[](https://github.com/apache/cordova-android/actions?query=branch%3Amaster)
|
||||
[](https://codecov.io/github/apache/cordova-android?branch=master)
|
||||
|
||||
- Java JDK 1.5
|
||||
- Apache ANT
|
||||
- Android SDK [http://developer.android.com](http://developer.android.com)
|
||||
- Apache Commons Codec [http://commons.apache.org/codec/](http://commons.apache.org/codec/)
|
||||
Cordova Android is an Android application library that allows for Cordova-based projects to be built for the Android Platform. Cordova based applications are, at the core, applications written with web technology: HTML, CSS and JavaScript.
|
||||
|
||||
Test Requirements
|
||||
---
|
||||
- JUnit - [https://github.com/KentBeck/junit](https://github.com/KentBeck/junit)
|
||||
|
||||
Building
|
||||
---
|
||||
[Apache Cordova](https://cordova.apache.org) is a project of The Apache Software Foundation (ASF).
|
||||
|
||||
To create your cordova.jar, copy the commons codec:
|
||||
## Requires
|
||||
|
||||
mv commons-codec-1.6.jar framework/libs
|
||||
- Java JDK 1.8
|
||||
- Android SDK [http://developer.android.com](https://developer.android.com/)
|
||||
|
||||
then run in the framework directory:
|
||||
## Cordova Android Developer Tools
|
||||
|
||||
android update project -p . -t android-15
|
||||
ant jar
|
||||
Use the [Cordova command-line tool](https://www.npmjs.com/package/cordova) to create projects and install plugins.
|
||||
|
||||
## Using Android Studio
|
||||
|
||||
Cordova Android Developer Tools
|
||||
---
|
||||
1. Create a project
|
||||
2. Import it via "Non-Android Studio Project"
|
||||
|
||||
The Cordova developer tooling is split between general tooling and project level tooling.
|
||||
## Running the Native Tests
|
||||
|
||||
To enable the command-line tools available in the ./bin directory, make
|
||||
sure you have all of the dependencies installed. You will need
|
||||
[NodeJS](http://nodejs.org) (which should come with `npm`). To install
|
||||
the dependencies:
|
||||
|
||||
$ cd bin
|
||||
$ npm install
|
||||
|
||||
General Commands
|
||||
|
||||
./bin/create [path package activity] ... create the ./example app or a cordova android project
|
||||
./bin/bench ............................ generate a bench proj
|
||||
./bin/autotest ......................... test the cli tools
|
||||
./bin/test ............................. run mobile-spec
|
||||
|
||||
Project Commands
|
||||
|
||||
These commands live in a generated Cordova Android project.
|
||||
|
||||
./cordovap/debug [path] ..................... install to first device
|
||||
./cordova/emulate .......................... start avd (emulator) named default
|
||||
./cordova/log .............................. starts logcat
|
||||
|
||||
Running the Example Project
|
||||
---
|
||||
|
||||
Start avd (emulator) named `default`:
|
||||
|
||||
./bin/emulate
|
||||
|
||||
Create the example project and build it to the first device:
|
||||
|
||||
./bin/create
|
||||
cd example
|
||||
./cordova/debug
|
||||
|
||||
Start adb logcat (console.log calls output here):
|
||||
|
||||
./cordova/log
|
||||
|
||||
Running the [callback/callback-test](http://github.com/callback/callback-test) tests:
|
||||
---
|
||||
|
||||
./bin/test
|
||||
|
||||
Creating a new Cordova Android Project
|
||||
---
|
||||
|
||||
./bin/create ~/Desktop/myapp com.phonegap.special MyApp
|
||||
|
||||
Importing a Cordova Android Project into Eclipse
|
||||
----
|
||||
|
||||
1. File > New > Project...
|
||||
2. Android > Android Project
|
||||
3. Create project from existing source (point to the generated app found in tmp/android)
|
||||
4. Right click on libs/cordova.jar and add to build path
|
||||
5. Right click on the project root: Run as > Run Configurations
|
||||
6. Click on the Target tab and select Manual (this way you can choose the emulator or device to build to)
|
||||
|
||||
Running Tests
|
||||
----
|
||||
Please see details under test/README.md.
|
||||
|
||||
Further Reading
|
||||
---
|
||||
|
||||
- [http://developer.android.com](http://developer.android.com)
|
||||
- [http://docs.phonegap.com](http://docs.phonegap.com)
|
||||
- [http://wiki.phonegap.com](http://wiki.phonegap.com)
|
||||
The `test/` directory in this project contains an Android test project that can be used to run different kinds of native tests. Check out the [README contained therein](test/README.md) for more details!
|
||||
|
||||
986
RELEASENOTES.md
Normal file
@@ -0,0 +1,986 @@
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
## Release Notes for Cordova (Android)
|
||||
|
||||
### 10.0.0 (Jul 17, 2021)
|
||||
|
||||
**Breaking:**
|
||||
|
||||
* [GH-1052](https://github.com/apache/cordova-android/pull/1052) feat!: only support `AndroidX`
|
||||
* [GH-1137](https://github.com/apache/cordova-android/pull/1137) feat!: implement `WebViewAssetLoader`
|
||||
* [GH-1268](https://github.com/apache/cordova-android/pull/1268) feat!: release build defaults to `aab` package type
|
||||
* [GH-1182](https://github.com/apache/cordova-android/pull/1182) feat!: bump `target sdk@30` w/ `build-tool@30.0.3`
|
||||
* [GH-1257](https://github.com/apache/cordova-android/pull/1257) feat!: upgrade `gradle@7.1.1`
|
||||
* [GH-1197](https://github.com/apache/cordova-android/pull/1197) feat!: upgrade `gradle@6.8.3`
|
||||
* [GH-1256](https://github.com/apache/cordova-android/pull/1256) feat!: upgrade `kotlin@1.5.20`
|
||||
* [GH-1204](https://github.com/apache/cordova-android/pull/1204) feat!: upgrade `kotlin@1.4.32`
|
||||
* [GH-1200](https://github.com/apache/cordova-android/pull/1200) feat!: upgrade `kotlin@1.4.31`
|
||||
* [GH-1255](https://github.com/apache/cordova-android/pull/1255) feat!: upgrade `android-gradle-plugin@4.2.2`
|
||||
* [GH-1232](https://github.com/apache/cordova-android/pull/1232) feat!: upgrade `android-gradle-plugin@4.2.1`
|
||||
* [GH-1198](https://github.com/apache/cordova-android/pull/1198) feat!: upgrade `android-gradle-plugin@4.1.3`
|
||||
* [GH-1199](https://github.com/apache/cordova-android/pull/1199) feat!: upgrade `Google Services Gradle Plugin@4.3.5`
|
||||
* [GH-1262](https://github.com/apache/cordova-android/pull/1262) feat!: bump `appcompat@1.3.0`
|
||||
* [GH-1258](https://github.com/apache/cordova-android/pull/1258) feat!: bump `android.webkit@1.4.0`
|
||||
* [GH-1252](https://github.com/apache/cordova-android/pull/1252) feat!: drop abandoned `com.github.dcendents:android-maven-gradle-plugin`
|
||||
* [GH-1212](https://github.com/apache/cordova-android/pull/1212) feat!: unify & fix gradle library/tooling overrides
|
||||
* [GH-1138](https://github.com/apache/cordova-android/pull/1138) feat(allow-list)!: integrate and refactor core plugin
|
||||
* [GH-1201](https://github.com/apache/cordova-android/pull/1201) feat!: upgrade jfrog `gradle-bintray-plugin@1.8.5`
|
||||
* [GH-1279](https://github.com/apache/cordova-android/pull/1279) chore!: bump all dependencies
|
||||
* [GH-1278](https://github.com/apache/cordova-android/pull/1278) chore!: drop `node` 10 support
|
||||
* [GH-1205](https://github.com/apache/cordova-android/pull/1205) chore! (`npm`): update all dependencies
|
||||
* [GH-1274](https://github.com/apache/cordova-android/pull/1274) cleanup!: remove deprecated settings & add todo comments
|
||||
* [GH-1048](https://github.com/apache/cordova-android/pull/1048) cleanup!: remove `keystore` password prompt
|
||||
* [GH-1251](https://github.com/apache/cordova-android/pull/1251) cleanup!: drop `jcenter` & update dependencies
|
||||
* [GH-1269](https://github.com/apache/cordova-android/pull/1269) refactor!: do not copy JS lib to platform project
|
||||
* [GH-1270](https://github.com/apache/cordova-android/pull/1270) refactor(Api)!: use version from `package.json`
|
||||
* [GH-1266](https://github.com/apache/cordova-android/pull/1266) refactor(run)!: `run` method
|
||||
* [GH-1083](https://github.com/apache/cordova-android/pull/1083) refactor!: drop support for `android` SDK tool
|
||||
* [GH-1100](https://github.com/apache/cordova-android/pull/1100) refactor!: remove most platform binaries
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1241](https://github.com/apache/cordova-android/pull/1241) feat: remove `java` 1.8 version check
|
||||
* [GH-1254](https://github.com/apache/cordova-android/pull/1254) feat: support `webkit` version override
|
||||
* [GH-1229](https://github.com/apache/cordova-android/pull/1229) feat: `CORDOVA_JAVA_HOME` env variable
|
||||
* [GH-1222](https://github.com/apache/cordova-android/pull/1222) feat: add backwards compatibility mode for `WebViewAssetLoader`
|
||||
* [GH-1166](https://github.com/apache/cordova-android/pull/1166) feat: overload `PluginEntry` constructor to set onload property
|
||||
* [GH-1208](https://github.com/apache/cordova-android/pull/1208) feat: allow `appcompat` version to be configurable
|
||||
* [GH-1047](https://github.com/apache/cordova-android/pull/1047) feat: Deprecated `onRequestPermissionResult` in favour for `onRequestPermissionsResult` for consistency
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1283](https://github.com/apache/cordova-android/pull/1283) fix: add missing apache-license header to `getASPath.bat`
|
||||
* [GH-1275](https://github.com/apache/cordova-android/pull/1275) fix: add `WebViewAssetloader` to default allow list
|
||||
* [GH-1216](https://github.com/apache/cordova-android/pull/1216) fix: request focus after custom view hided
|
||||
* [GH-1264](https://github.com/apache/cordova-android/pull/1264) fix: missing `super.onRequestPermissionsResult` error (`MissingSuperCall`)
|
||||
* [GH-563](https://github.com/apache/cordova-android/pull/563) fix(build): support tilde expansion on Windows
|
||||
* [GH-1220](https://github.com/apache/cordova-android/pull/1220) fix(`requirements` check): use regex to get java version from javac output
|
||||
* [GH-1227](https://github.com/apache/cordova-android/pull/1227) fix(prepare): delete splash screens if none are used
|
||||
* [GH-1228](https://github.com/apache/cordova-android/pull/1228) fix: java checks
|
||||
* [GH-1276](https://github.com/apache/cordova-android/pull/1276) fix: remove forced default `gradle.daemon` setting
|
||||
|
||||
**Refactors:**
|
||||
|
||||
* [GH-1265](https://github.com/apache/cordova-android/pull/1265) refactor: do not infer project root from script location
|
||||
* [GH-1267](https://github.com/apache/cordova-android/pull/1267) refactor: use target SDK of built APK to determine best emulator
|
||||
* [GH-1253](https://github.com/apache/cordova-android/pull/1253) refactor: `gradle` cleanup
|
||||
* [GH-1260](https://github.com/apache/cordova-android/pull/1260) refactor(`check_reqs`): drop `originalError` param from `check_android_target`
|
||||
* [GH-1246](https://github.com/apache/cordova-android/pull/1246) refactor(`env/java`): improve tests and implementation
|
||||
|
||||
**Chores & Cleanup:**
|
||||
|
||||
* [GH-1273](https://github.com/apache/cordova-android/pull/1273) chore: remove old `VERSION` file
|
||||
* [GH-1272](https://github.com/apache/cordova-android/pull/1272) cleanup: delete old ANT & Eclipse files
|
||||
* [GH-1141](https://github.com/apache/cordova-android/pull/1141) cleanup: remove app cache settings
|
||||
|
||||
**CI, Build & Testing:**
|
||||
|
||||
* [GH-1218](https://github.com/apache/cordova-android/pull/1218) ci: Add `Node16` to CI matrix
|
||||
* [GH-1271](https://github.com/apache/cordova-android/pull/1271) build: build `cordova.js` during npm prepare
|
||||
* [GH-1207](https://github.com/apache/cordova-android/pull/1207) test(`AndroidManifest`): update theme to `Theme.AppCompat.NoActionBar`
|
||||
* [GH-1263](https://github.com/apache/cordova-android/pull/1263) test(`check_reqs`): do not hardcode `DEFAULT_TARGET_API`
|
||||
* [GH-1259](https://github.com/apache/cordova-android/pull/1259) test(`prepare`): factor out common vars
|
||||
|
||||
### 9.1.0 (Apr 09, 2021)
|
||||
|
||||
**Features:**
|
||||
|
||||
* [GH-1104](https://github.com/apache/cordova-android/pull/1104) feat: support `gzip` encoding requests & use `GZIPInputStream`
|
||||
* [GH-1167](https://github.com/apache/cordova-android/pull/1167) feat: handle `intent://` scheme links with `browser_fallback_url` param
|
||||
* [GH-1179](https://github.com/apache/cordova-android/pull/1179) feat: add `repositories` support
|
||||
* [GH-1173](https://github.com/apache/cordova-android/pull/1173) feat(android-studio): display app name as project name
|
||||
* [GH-1113](https://github.com/apache/cordova-android/pull/1113) feat: `webp` support for splashscreen
|
||||
* [GH-1125](https://github.com/apache/cordova-android/pull/1125) feat(Adb): list `devices` _and_ `emulators` in one go
|
||||
|
||||
**Fixes:**
|
||||
|
||||
* [GH-1186](https://github.com/apache/cordova-android/pull/1186) fix: copy `repositories.gradle` to project on create
|
||||
* [GH-1184](https://github.com/apache/cordova-android/pull/1184) fix: unit-test failure
|
||||
* [GH-733](https://github.com/apache/cordova-android/pull/733) fix(splashscreen): nav & title bar showing in fullscreen mode
|
||||
* [GH-1157](https://github.com/apache/cordova-android/pull/1157) fix: restore key event handlers when DOM element is fullscreen
|
||||
* [GH-1073](https://github.com/apache/cordova-android/pull/1073) fix(android): Avoid Crash Report: ConcurrentModificationException
|
||||
* [GH-1148](https://github.com/apache/cordova-android/pull/1148) fix: add not null checks to prevent running on destroyed activity
|
||||
* [GH-1091](https://github.com/apache/cordova-android/pull/1091) fix: concurrent modification exception (#924)
|
||||
* [GH-1153](https://github.com/apache/cordova-android/pull/1153) fix: optional arch parameter
|
||||
* [GH-1136](https://github.com/apache/cordova-android/pull/1136) fix(prepare): `mapImageResources` always returning `[]`
|
||||
* [GH-1111](https://github.com/apache/cordova-android/pull/1111) fix(android): allow file access for existing behavior
|
||||
* [GH-1045](https://github.com/apache/cordova-android/pull/1045) fix: Reflect minimum required NodeJS
|
||||
* [GH-1084](https://github.com/apache/cordova-android/pull/1084) fix(prepare): fix pattern used to collect image resources
|
||||
* [GH-1014](https://github.com/apache/cordova-android/pull/1014) fix(`pluginHandlers`): properly check if path is inside another
|
||||
* [GH-1018](https://github.com/apache/cordova-android/pull/1018) fix: gradle ignore properties
|
||||
* [GH-1185](https://github.com/apache/cordova-android/pull/1185) fix(regression): Cannot read version of undefined caused by Java refactor
|
||||
* [GH-1117](https://github.com/apache/cordova-android/pull/1117) fix: allow changing min sdk version
|
||||
|
||||
**Refactors:**
|
||||
|
||||
* [GH-1101](https://github.com/apache/cordova-android/pull/1101) refactor: unify target resolution for devices & emulators
|
||||
* [GH-1130](https://github.com/apache/cordova-android/pull/1130) refactor: java checks
|
||||
* [GH-1099](https://github.com/apache/cordova-android/pull/1099) refactor(`ProjectBuilder`): clean up output file collection code
|
||||
* [GH-1123](https://github.com/apache/cordova-android/pull/1123) refactor: unify installation on devices & emulators
|
||||
* [GH-1102](https://github.com/apache/cordova-android/pull/1102) refactor(`check_reqs`): cleanup default Java location detection on **Windows**
|
||||
* [GH-1103](https://github.com/apache/cordova-android/pull/1103) refactor: do not kill adb on UNIX-like systems
|
||||
* [GH-1086](https://github.com/apache/cordova-android/pull/1086) refactor(retry): simplify retryPromise using modern JS
|
||||
* [GH-1085](https://github.com/apache/cordova-android/pull/1085) refactor(utils): reduce number of utils
|
||||
* [GH-1046](https://github.com/apache/cordova-android/pull/1046) refactor: Stop suppressing un-needed TruelyRandom lints
|
||||
* [GH-1016](https://github.com/apache/cordova-android/pull/1016) refactor: save `ProjectBuilder` instance in Api instance
|
||||
* [GH-1108](https://github.com/apache/cordova-android/pull/1108) refactor: remove copied Adb.install from `emulator.install`
|
||||
|
||||
**Chores:**
|
||||
|
||||
* [GH-1196](https://github.com/apache/cordova-android/pull/1196) chore: add missing header license
|
||||
* chore(asf): Update GitHub repo metadata
|
||||
* [GH-1183](https://github.com/apache/cordova-android/pull/1183) chore: rebuilt package-lock
|
||||
* [GH-1015](https://github.com/apache/cordova-android/pull/1015) chore: remove unnecessary stuff
|
||||
* [GH-1081](https://github.com/apache/cordova-android/pull/1081) chore(pkg): remove deprecated `no-op` field `"engineStrict"`
|
||||
* [GH-1019](https://github.com/apache/cordova-android/pull/1019) chore: remove unused `emulator.create_image` and its dependencies
|
||||
|
||||
**Tests & CI:**
|
||||
|
||||
* [GH-1017](https://github.com/apache/cordova-android/pull/1017) test(java): fix, improve and move clean script
|
||||
* [GH-1012](https://github.com/apache/cordova-android/pull/1012) test: fix missing stack traces in jasmine output
|
||||
* [GH-1013](https://github.com/apache/cordova-android/pull/1013) test(`pluginHandlers/common`): better setup & teardown
|
||||
* [GH-1094](https://github.com/apache/cordova-android/pull/1094) test: fix unit test failures for certain random orders
|
||||
* [GH-1094](https://github.com/apache/cordova-android/pull/1094) test: ensure single top-level describe block in test file
|
||||
* [GH-1129](https://github.com/apache/cordova-android/pull/1129) test(java): remove duplicate code in `BackButtonMultipageTest`
|
||||
* [GH-975](https://github.com/apache/cordova-android/pull/975) ci: Added Node 14.x
|
||||
|
||||
### 9.0.0 (Jun 23, 2020)
|
||||
|
||||
* [GH-1005](https://github.com/apache/cordova-android/pull/1005) chore: set AndroidX off by default
|
||||
* [GH-971](https://github.com/apache/cordova-android/pull/971) fix: Accept multiple mime types on file input
|
||||
* [GH-1001](https://github.com/apache/cordova-android/pull/1001) fix: support both adaptive and standard icons at the same time
|
||||
* [GH-985](https://github.com/apache/cordova-android/pull/985) fix: Plugin install fails when preview sdk is installed
|
||||
* [GH-994](https://github.com/apache/cordova-android/pull/994) chore: cleanup yaml files
|
||||
* [GH-999](https://github.com/apache/cordova-android/pull/999) chore: remove trailing spaces from Java sources
|
||||
* [GH-992](https://github.com/apache/cordova-android/pull/992) chore: update some dependencies
|
||||
* [GH-998](https://github.com/apache/cordova-android/pull/998) chore: remove trailing spaces from framework build files
|
||||
* [GH-997](https://github.com/apache/cordova-android/pull/997) chore: remove trailing spaces from project template
|
||||
* [GH-996](https://github.com/apache/cordova-android/pull/996) chore: remove trailing spaces from bat files
|
||||
* [GH-995](https://github.com/apache/cordova-android/pull/995) remove trailing spaces from markdown files
|
||||
* [GH-993](https://github.com/apache/cordova-android/pull/993) chore: update `devDependencies`
|
||||
* [GH-987](https://github.com/apache/cordova-android/pull/987) breaking: reduce combined response cutoff to 16 MB
|
||||
* [GH-988](https://github.com/apache/cordova-android/pull/988) major: Gradle 6.5 & **Android** Gradle plugin 4.0.0 updates
|
||||
* [GH-990](https://github.com/apache/cordova-android/pull/990) chore: remove trailing spaces from `app/build.gradle`
|
||||
* [GH-989](https://github.com/apache/cordova-android/pull/989) breaking: remove `legacy/build.gradle` from template
|
||||
* [GH-978](https://github.com/apache/cordova-android/pull/978) fix: `wait_for_boot` waiting forever
|
||||
* [GH-965](https://github.com/apache/cordova-android/pull/965) fix: Increased `detectArchitecture()` timeout
|
||||
* [GH-962](https://github.com/apache/cordova-android/pull/962) breaking: Bump **Android** gradle plugin to 3.6.0
|
||||
* [GH-948](https://github.com/apache/cordova-android/pull/948) feature: JVM Args flag
|
||||
* [GH-951](https://github.com/apache/cordova-android/pull/951) fix: `ANDROID_SDK_ROOT` variable
|
||||
* [GH-959](https://github.com/apache/cordova-android/pull/959) test: synced AndroidX gradle versions to the same version as the **Android** test
|
||||
* [GH-960](https://github.com/apache/cordova-android/pull/960) feat: `com.android.tools.build:gradle:3.5.3`
|
||||
* [GH-956](https://github.com/apache/cordova-android/pull/956) chore(npm): add `package-lock.json`
|
||||
* [GH-958](https://github.com/apache/cordova-android/pull/958) chore(npm): add ignore list
|
||||
* [GH-957](https://github.com/apache/cordova-android/pull/957) chore: various cleanup
|
||||
* [GH-955](https://github.com/apache/cordova-android/pull/955) chore(eslint): bump package & apply eslint fix
|
||||
* [GH-954](https://github.com/apache/cordova-android/pull/954) breaking(npm): bump packages
|
||||
* [GH-953](https://github.com/apache/cordova-android/pull/953) chore(npm): use short notation in `package.json`
|
||||
* [GH-823](https://github.com/apache/cordova-android/pull/823) fix: prevent exit fullscreen mode from closing application
|
||||
* [GH-950](https://github.com/apache/cordova-android/pull/950) fix: removed redundent logcat print
|
||||
* [GH-915](https://github.com/apache/cordova-android/pull/915) breaking: bump minSdkVersion to 22 and drop pre-Lollipop specific code
|
||||
* [GH-941](https://github.com/apache/cordova-android/pull/941) fix: GH-873 App bundle builds to obey command-line arguments
|
||||
* [GH-940](https://github.com/apache/cordova-android/pull/940) ci: drop travis & move codecov to gh-actions
|
||||
* [GH-929](https://github.com/apache/cordova-android/pull/929) chore: updated `README` to reflect what **Android** requires more accurately, which is Java 8, not anything less, not anything greater. Java 1.8.x is required.
|
||||
* [GH-937](https://github.com/apache/cordova-android/pull/937) fix: GH-935 replaced `compare-func` with native sort method
|
||||
* [GH-939](https://github.com/apache/cordova-android/pull/939) fix: test failure with shebang interpreter in `rewired` files
|
||||
* [GH-911](https://github.com/apache/cordova-android/pull/911) refactor: use es6 class
|
||||
* [GH-910](https://github.com/apache/cordova-android/pull/910) refactor (eslint): use `cordova-eslint`
|
||||
* [GH-909](https://github.com/apache/cordova-android/pull/909) chore: remove appveyor residual
|
||||
* [GH-895](https://github.com/apache/cordova-android/pull/895) feat: add github actions
|
||||
* [GH-842](https://github.com/apache/cordova-android/pull/842) refactor: remove `shelljs` dependency
|
||||
* [GH-896](https://github.com/apache/cordova-android/pull/896) feat: add Kotlin support
|
||||
* [GH-901](https://github.com/apache/cordova-android/pull/901) feat: add AndroidX support
|
||||
* [GH-849](https://github.com/apache/cordova-android/pull/849) fix: cordova requirements consider the `android-targetSdkVersion`
|
||||
* [GH-904](https://github.com/apache/cordova-android/pull/904) fix (adb): shell to return expected stdout
|
||||
* [GH-792](https://github.com/apache/cordova-android/pull/792) feat: upgrade `gradle` to 6.1 & gradle build tools to 3.5.3
|
||||
* [GH-902](https://github.com/apache/cordova-android/pull/902) chore: remove `.project` file & add `.settings` to `gitignore`
|
||||
* [GH-900](https://github.com/apache/cordova-android/pull/900) refactor: simplify `doFindLatestInstalledBuildTools`
|
||||
* [GH-751](https://github.com/apache/cordova-android/pull/751) feat: use Java package name for loading `BuildConfig`
|
||||
* [GH-898](https://github.com/apache/cordova-android/pull/898) chore: rename gradle plugin google services `preference` options
|
||||
* [GH-893](https://github.com/apache/cordova-android/pull/893) feat: add Google Services support
|
||||
* [GH-709](https://github.com/apache/cordova-android/pull/709) feat: add `version-compare` library to compare `build-tools` versions properly.
|
||||
* [GH-831](https://github.com/apache/cordova-android/pull/831) chore: ignore auto-generated eclipse buildship files
|
||||
* [GH-848](https://github.com/apache/cordova-android/pull/848) breaking: increased default target sdk to 29
|
||||
* [GH-859](https://github.com/apache/cordova-android/pull/859) breaking: removed unnecessary project name restriction
|
||||
* [GH-833](https://github.com/apache/cordova-android/pull/833) chore: drop `q` module
|
||||
* [GH-862](https://github.com/apache/cordova-android/pull/862) chore: replace `superspawn` & `child_process` with `execa`
|
||||
* [GH-860](https://github.com/apache/cordova-android/pull/860) feat: don't filter gradle's stderr anymore
|
||||
* [GH-832](https://github.com/apache/cordova-android/pull/832) chore: drop node 6 and 8 support
|
||||
* [GH-890](https://github.com/apache/cordova-android/pull/890) chore: bump version to 9.0.0-dev
|
||||
* [GH-697](https://github.com/apache/cordova-android/pull/697) chore: optimization code
|
||||
* [GH-863](https://github.com/apache/cordova-android/pull/863) chore: removed comment that serves no purpose
|
||||
* [GH-861](https://github.com/apache/cordova-android/pull/861) chore: update `jasmine` to 3.5.0
|
||||
* [GH-858](https://github.com/apache/cordova-android/pull/858) chore: modernize our one E2E test
|
||||
* [GH-854](https://github.com/apache/cordova-android/pull/854) chore: ensure to lint as many files as possible
|
||||
|
||||
### 8.1.0 (Sep 11, 2019)
|
||||
|
||||
* [GH-827](https://github.com/apache/cordova-android/pull/827) chore: bump dependencies for release 8.1.0
|
||||
* [GH-651](https://github.com/apache/cordova-android/pull/651) feat: added multiple selection for filepicker
|
||||
* [GH-672](https://github.com/apache/cordova-android/pull/672) chore: compress files in /res with tinypng.com
|
||||
* [GH-815](https://github.com/apache/cordova-android/pull/815) fix: `clean` command
|
||||
* [GH-750](https://github.com/apache/cordova-android/pull/750) Don't request focus explicitly if not needed
|
||||
* [GH-800](https://github.com/apache/cordova-android/pull/800) [GH-799](https://github.com/apache/cordova-android/pull/799) (android) Stop webview from restarting when activity resizes
|
||||
* [GH-764](https://github.com/apache/cordova-android/pull/764) feat: Build app bundles (.aab files)
|
||||
* [GH-788](https://github.com/apache/cordova-android/pull/788) Simplify `apkSorter` using `compare-func` package
|
||||
* [GH-787](https://github.com/apache/cordova-android/pull/787) Simplify and fix promise handling in specs
|
||||
* [GH-784](https://github.com/apache/cordova-android/pull/784) Properly handle promise in create script
|
||||
* [GH-783](https://github.com/apache/cordova-android/pull/783) Do not clobber process properties with test mocks
|
||||
* [GH-782](https://github.com/apache/cordova-android/pull/782) Do not clobber `console.log` to spy on it
|
||||
* [GH-724](https://github.com/apache/cordova-android/pull/724) Add Node.js 12 to CI Services
|
||||
* [GH-777](https://github.com/apache/cordova-android/pull/777) ci(travis): set `dist: trusty` in `.travis.yml`
|
||||
* [GH-779](https://github.com/apache/cordova-android/pull/779) Consistent order from `ProjectBuilder.apkSorter`
|
||||
* [GH-778](https://github.com/apache/cordova-android/pull/778) test: use verbose spec reporter
|
||||
* [GH-774](https://github.com/apache/cordova-android/pull/774) `rewire` workaround for NodeJS 12
|
||||
* [GH-772](https://github.com/apache/cordova-android/pull/772) `nyc@14` update in devDependencies
|
||||
* [GH-765](https://github.com/apache/cordova-android/pull/765) ci(travis): Fix **Android** SDK
|
||||
* [GH-713](https://github.com/apache/cordova-android/pull/713) Do not explicitly require modules from project directory
|
||||
* [GH-676](https://github.com/apache/cordova-android/pull/676) Added allprojects repositories for Framework Release Builds
|
||||
* [GH-699](https://github.com/apache/cordova-android/pull/699) Improve Gradle Build Arguments
|
||||
* [GH-710](https://github.com/apache/cordova-android/pull/710) Fix deprecation warning in `SystemCookieManager`
|
||||
* [GH-691](https://github.com/apache/cordova-android/pull/691) [GH-690](https://github.com/apache/cordova-android/pull/690): Run `prepare` with the correct `ConfigParser`
|
||||
* [GH-673](https://github.com/apache/cordova-android/pull/673) Updated `Android_HOME` Test to Follow [GH-656](https://github.com/apache/cordova-android/pull/656) Change
|
||||
|
||||
### 8.0.0 (Feb 13, 2019)
|
||||
* [GH-669](https://github.com/apache/cordova-android/pull/669) Added Missing License Headers
|
||||
* [GH-655](https://github.com/apache/cordova-android/pull/655) Use custom Gradle properties to read minSdkVersion value from `config.xml`
|
||||
* [GH-656](https://github.com/apache/cordova-android/pull/656) Quick fix to support **Android**_SDK_ROOT
|
||||
* [GH-632](https://github.com/apache/cordova-android/pull/632) Ignore more Gradle build artifacts in **Android** project
|
||||
* [GH-642](https://github.com/apache/cordova-android/pull/642) **Android** tools 3.3 & **Gradle** 4.10.3 update
|
||||
* [GH-654](https://github.com/apache/cordova-android/pull/654) Quick updates to top-level `project.properties`
|
||||
* [GH-635](https://github.com/apache/cordova-android/pull/635) Ignore **Android** Studio `.idea` files in project
|
||||
* [GH-624](https://github.com/apache/cordova-android/pull/624) Add missing log to Java version check
|
||||
* [GH-630](https://github.com/apache/cordova-android/pull/630) Update `emulator.js` to fix issue [GH-608](https://github.com/apache/cordova-android/pull/608)
|
||||
* [GH-626](https://github.com/apache/cordova-android/pull/626) Added `package-lock.json` to `.gitignore`
|
||||
* [GH-620](https://github.com/apache/cordova-android/pull/620) Fix requirements error messages for JDK 8
|
||||
* [GH-619](https://github.com/apache/cordova-android/pull/619) javac error message fixes in requirements check
|
||||
* [GH-612](https://github.com/apache/cordova-android/pull/612) Android Platform Release Preparation (Cordova 9)
|
||||
* [GH-607](https://github.com/apache/cordova-android/pull/607) Copy `node_modules` if the directory exists
|
||||
* [GH-582](https://github.com/apache/cordova-android/pull/582) Improve Test `README`
|
||||
* [GH-589](https://github.com/apache/cordova-android/pull/589) Rewrite install dir resolution for legacy plugins
|
||||
* [GH-572](https://github.com/apache/cordova-android/pull/572) Resolve issue with plugin `target-dir="app*"` subdirs
|
||||
* [GH-567](https://github.com/apache/cordova-android/pull/567) Output current package name if package name can't be validated
|
||||
* [GH-507](https://github.com/apache/cordova-android/pull/507) Gradle Updates
|
||||
* [GH-559](https://github.com/apache/cordova-android/pull/559) Eslint ignore version file
|
||||
* [GH-550](https://github.com/apache/cordova-android/pull/550) Fix for old plugins with non-Java sources
|
||||
* [GH-558](https://github.com/apache/cordova-android/pull/558) Update `cordova.js` from `cordova-js@4.2.3`
|
||||
* [GH-553](https://github.com/apache/cordova-android/pull/553) Check for `build-extras.gradle` in the app-parent directory
|
||||
* [GH-551](https://github.com/apache/cordova-android/pull/551) Add missing cast for `cdvMinSdkVersion`
|
||||
* [GH-539](https://github.com/apache/cordova-android/pull/539) Fix destination path fallback
|
||||
* [GH-544](https://github.com/apache/cordova-android/pull/544) Remove obsolete check for JellyBean
|
||||
* [GH-465](https://github.com/apache/cordova-android/pull/465) Removes Gradle property in-line command arguments for `gradle.properties`
|
||||
* [GH-523](https://github.com/apache/cordova-android/pull/523) Always put the Google repo above jcenter
|
||||
* [GH-486](https://github.com/apache/cordova-android/pull/486) Change deprecated "compile" to "implementation"
|
||||
* [GH-495](https://github.com/apache/cordova-android/pull/495) Incorrect default sdk version issue fix
|
||||
* [GH-493](https://github.com/apache/cordova-android/pull/493) Remove bundled dependencies
|
||||
* [GH-490](https://github.com/apache/cordova-android/pull/490) Fixes build & run related bugs from builder refactor
|
||||
* [GH-464](https://github.com/apache/cordova-android/pull/464) Unit tests for **Android**_sdk and **Android**Project
|
||||
* [GH-448](https://github.com/apache/cordova-android/pull/448) [CB-13685](https://issues.apache.org/jira/browse/CB-13685) Adaptive Icon Support
|
||||
* [GH-487](https://github.com/apache/cordova-android/pull/487) Do not attempt an activity intent AND a url load into the webview, return from the internal webview load.
|
||||
* [GH-461](https://github.com/apache/cordova-android/pull/461) Remove old builders code
|
||||
* [GH-463](https://github.com/apache/cordova-android/pull/463) Emulator: Add unit tests and remove Q
|
||||
* [GH-462](https://github.com/apache/cordova-android/pull/462) Device: Add unit tests and remove Q
|
||||
* [GH-457](https://github.com/apache/cordova-android/pull/457) Emulator: handle "device still connecting" error
|
||||
* [GH-445](https://github.com/apache/cordova-android/pull/445) Run and retryPromise improvements and tests
|
||||
* [GH-453](https://github.com/apache/cordova-android/pull/453) Lint JS files w/out extension too
|
||||
* [GH-452](https://github.com/apache/cordova-android/pull/452) Emit log event instead of logging directly
|
||||
* [GH-449](https://github.com/apache/cordova-android/pull/449) Increase old plugin compatibility
|
||||
* [GH-442](https://github.com/apache/cordova-android/pull/442) Fixes and cleanup for Java tests and CI
|
||||
* [GH-446](https://github.com/apache/cordova-android/pull/446) [CB-14101](https://issues.apache.org/jira/browse/CB-14101) Fix Java version check for Java >= 9
|
||||
* [CB-14127](https://issues.apache.org/jira/browse/CB-14127) Move google maven repo ahead of jcenter
|
||||
* [CB-14038](https://issues.apache.org/jira/browse/CB-14038) Fix false positive detecting project type
|
||||
* [CB-14008](https://issues.apache.org/jira/browse/CB-14008) Updating Gradle Libraries to work with **Android** Studio 3.1.0
|
||||
* [CB-13975](https://issues.apache.org/jira/browse/CB-13975) Fix to fire pause event when cdvStartInBackground=true
|
||||
* [CB-13830](https://issues.apache.org/jira/browse/CB-13830) Add handlers for plugins that use non-Java source files, such as Camera
|
||||
* [CB-13923](https://issues.apache.org/jira/browse/CB-13923) Fix -1 length for compressed files
|
||||
|
||||
### 7.1.0 (Feb 20, 2018)
|
||||
* [CB-13879](https://issues.apache.org/jira/browse/CB-13879) updated gradle tools dependency to 3.0.1 for project template
|
||||
* [CB-13831](https://issues.apache.org/jira/browse/CB-13831) Update `android-versions` to 1.3.0 to support SDK 27.
|
||||
* [CB-13800](https://issues.apache.org/jira/browse/CB-13800) Drop pre-KitKat specific code
|
||||
* [CB-13724](https://issues.apache.org/jira/browse/CB-13724) Updated the **Android** Tooling required for the latest version on both the test project, and the template
|
||||
* [CB-13724](https://issues.apache.org/jira/browse/CB-13724) Bump Target SDK to API 27
|
||||
* [CB-13646](https://issues.apache.org/jira/browse/CB-13646) Using the deprecated `NDK` by default breaks the build. Crosswalk users need to specify the Gradle parameters to keep it working.
|
||||
* [CB-12218](https://issues.apache.org/jira/browse/CB-12218) Fix consistency of null result message
|
||||
* [CB-13571](https://issues.apache.org/jira/browse/CB-13571) Prevent crash with unrecognized **Android** version
|
||||
* [CB-13721](https://issues.apache.org/jira/browse/CB-13721) Fix build apps that use `cdvHelpers.getConfigPreference`
|
||||
* [CB-13621](https://issues.apache.org/jira/browse/CB-13621) Wrote similar warning to [CB-12948](https://issues.apache.org/jira/browse/CB-12948) on **iOS**. We no longer support `cordova update` command.
|
||||
|
||||
### 7.0.0 (Nov 30, 2017)
|
||||
* [CB-13612](https://issues.apache.org/jira/browse/CB-13612) Fix the remapper so that XML files copy over and the Camera works again.
|
||||
* [CB-13741](https://issues.apache.org/jira/browse/CB-13741) Bump `package.json` so we can install plugins
|
||||
* [CB-13610](https://issues.apache.org/jira/browse/CB-13610) Compress the default app assets
|
||||
* [CB-12835](https://issues.apache.org/jira/browse/CB-12835) add a Context getter in CordovaInterface
|
||||
* [CB-8976](https://issues.apache.org/jira/browse/CB-8976) Added the `cdvVersionCodeForceAbiDigit` flag to the template build.gradle that appends 0 to the versionCode when `cdvBuildMultipleApks` is not set
|
||||
* [CB-12291](https://issues.apache.org/jira/browse/CB-12291) (android) Add x86_64, arm64 and armeabi architecture flavors
|
||||
* [CB-13602](https://issues.apache.org/jira/browse/CB-13602) We were setting the path wrong, this is hacky but it works
|
||||
* [CB-13601](https://issues.apache.org/jira/browse/CB-13601) Fixing the standalone run scripts to make sure this works without using the CLI
|
||||
* [CB-13580](https://issues.apache.org/jira/browse/CB-13580) fix build for multiple apks (different product flavors)
|
||||
* [CB-13558](https://issues.apache.org/jira/browse/CB-13558) Upgrading the gradle so we can upload the AAR
|
||||
* [CB-13297](https://issues.apache.org/jira/browse/CB-13297) This just works once you bump the project structure. Java 1.8 compatibility baked-in
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) **Android** Studio 3 work, things have changed with how the platform is built
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) Found bug where the gradle subproject changes weren't actually getting written to the correct gradle file
|
||||
* [CB-13470](https://issues.apache.org/jira/browse/CB-13470) Fix Clean so that it cleans the **Android** Studio structure
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) Adding specs for resource files inside an **Android** Studio Project
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) Added remapping for drawables
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) Found bug in Api.js where xml/strings.xml is used instead of values/strings.xml
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) Setup Api.js to support multiple builders based on project structure
|
||||
* [CB-11244](https://issues.apache.org/jira/browse/CB-11244) Changing directory creation, will most likely hide this behind a flag for the next release of `cordova-android`, and then make it default in the next major pending feedback
|
||||
* Adding the Studio Builder to build a project based on **Android** Studio, and deleting Ant, since Google does not support Ant Builds anymore. Sorry guys!
|
||||
|
||||
### 6.4.0 (Nov 06, 2017)
|
||||
* [CB-13289](https://issues.apache.org/jira/browse/CB-13289) Fixing build problems with Studio Three, but keeping **Windows** Gradle fix for now, will be deprecated
|
||||
* [CB-13289](https://issues.apache.org/jira/browse/CB-13289) Fix test to work with new Google **Android** Gradle DSL
|
||||
* :CB-13501 : update appveyor node versions to support node 8
|
||||
* [CB-13499](https://issues.apache.org/jira/browse/CB-13499) Remove duplicate "setting" in error strings
|
||||
* Include missing values for task.name when 'cdvBuildMultipleApks' option is true, 'task.name' can have 'validateSigningArmv7Release' or 'validateSigningX86Release' values too.
|
||||
* [CB-13406](https://issues.apache.org/jira/browse/CB-13406) Fixed AVD API level comparison when choosing sub-par API level match. Added tests for the best_image method.
|
||||
* [CB-13404](https://issues.apache.org/jira/browse/CB-13404) add **Android**-versions to bundledDependencies. Ignore best emulator selection when parsed AVD information does not include API level in the target
|
||||
* [CB-12895](https://issues.apache.org/jira/browse/CB-12895) : eslint ignoring cordova.js
|
||||
* [CB-12895](https://issues.apache.org/jira/browse/CB-12895) Temporarily disabling eslint since cordova-js does not have eslint yet.
|
||||
|
||||
### 6.3.0 (Sep 25, 2017)
|
||||
* [CB-6936](https://issues.apache.org/jira/browse/CB-6936) fix crash when calling methods on a destroyed webview
|
||||
* [CB-12981](https://issues.apache.org/jira/browse/CB-12981) handle SDK 26.0.2 slightly different AVD list output for **Android** 8+ AVDs. Would cause "cannot read property replace of undefined" errors when trying to deploy an **Android** 8 emulator.
|
||||
* Updated maven repo to include most recent lib versions
|
||||
* [CB-13177](https://issues.apache.org/jira/browse/CB-13177) Updating to API Level 26
|
||||
* Revert [CB-12015](https://issues.apache.org/jira/browse/CB-12015) initial-scale values less than 1.0 are ignored on **Android**
|
||||
* [CB-12730](https://issues.apache.org/jira/browse/CB-12730) The Cordova Compatibility Plugin is now integrated into cordova-android
|
||||
* [CB-12453](https://issues.apache.org/jira/browse/CB-12453) Remove unnecessary double quotes from .bat files which are the causes of crash if project path contains spaces
|
||||
* [CB-13031](https://issues.apache.org/jira/browse/CB-13031) Fix bug with case-sensitivity of **Android**-packageName
|
||||
* [CB-10916](https://issues.apache.org/jira/browse/CB-10916) Support display name for **Android**
|
||||
* [CB-12423](https://issues.apache.org/jira/browse/CB-12423) make explicit JDK 1.8 or greater is needed in the `README`, we require 1.8 for compilation, but do not have 1.8 Java features yet
|
||||
* [CB-13006](https://issues.apache.org/jira/browse/CB-13006) removed create and update end-to-end tests, and instead added more unit test coverage. tweaked code coverage invocation so that we get coverage details on the create.js module. slight changes to the create.js module so that it is slightly easier to test.
|
||||
* [CB-12950](https://issues.apache.org/jira/browse/CB-12950) lots of tweaks for end-to-end test runs, especially on CI: - rename npm tasks to reflect what they do (npm run unit-tests, npm run e2e-tests). main `npm test` runs linter, unit tests and e2e tests now. - locked jasmine down to ~2.6.0. - consolidate gitignores. - updated travis to run `npm test`. add **Android** sdk installation to appveyor ci run.align **Android** dpendencies across travis and appveyor. have appveyor install gradle. force gradle to version 3.4.1 in appveyor, as that seems to be the only version choco has. explicitly invoke sdkmanager to move license accepting process along.
|
||||
* [CB-12605](https://issues.apache.org/jira/browse/CB-12605) In **Windows** get **Android** studio path from the registry
|
||||
* [CB-12762](https://issues.apache.org/jira/browse/CB-12762) : pointed `package.json` repo items to github mirrors instead of apache repos site
|
||||
* [CB-12617](https://issues.apache.org/jira/browse/CB-12617) : removed node0.x support for platforms and added engineStrict
|
||||
|
||||
### 6.2.3 (May 2, 2017)
|
||||
* [CB-12640](https://issues.apache.org/jira/browse/CB-12640) better handling of unrecognized Android SDK commands on **Windows**.
|
||||
* [CB-12640](https://issues.apache.org/jira/browse/CB-12640) flipped avd parsing logic so that it always tries to use avdmanager to retrieve avds first, then falls back to android command if avdmanager cannot be found (and errors with ENOENT). updated tests - and added explicit tests to ensure to shell out to singular forms of sub-commands when executing `android`
|
||||
* [CB-12640](https://issues.apache.org/jira/browse/CB-12640) support for android sdk tools 26.0.1.
|
||||
|
||||
### 6.2.2 (Apr 24, 2017)
|
||||
* [CB-12697](https://issues.apache.org/jira/browse/CB-12697) Updated checked-in `node_modules`
|
||||
|
||||
### 6.2.1 (Apr 02, 2017)
|
||||
* [CB-12621](https://issues.apache.org/jira/browse/CB-12621) reverted elementtree dep to 0.1.6
|
||||
|
||||
### 6.2.0 (Mar 28, 2017)
|
||||
* [CB-12614](https://issues.apache.org/jira/browse/CB-12614) Adding headers to tests
|
||||
* [CB-8978](https://issues.apache.org/jira/browse/CB-8978) Prepare copy `resource-files` from `config.xml`
|
||||
* [CB-12605](https://issues.apache.org/jira/browse/CB-12605) Fix a requirements check failure on **Windows**
|
||||
* [CB-12595](https://issues.apache.org/jira/browse/CB-12595) This should find an **Android Studio** installation and use the sweet gradle center found inside
|
||||
* [CB-12546](https://issues.apache.org/jira/browse/CB-12546) leverage `avdmanager` if `android` warns it is no longer useful, which happens in **Android SDK Tools 25.3.1**. Explicitly set the `CWD` of the spawned emulator process to workaround a recent google android sdk bug. Rename `android_sdk_version.js` to `android_sdk.js`, to better reflect its contents. Have `create.js` copy over the `android_sdk_version` batch file.
|
||||
* [CB-12524](https://issues.apache.org/jira/browse/CB-12524) Fix for missing gradle template error. This now fetches the template from inside of the **Android Studio** directory, and falls back to a locally installed Gradle instance
|
||||
* [CB-12465](https://issues.apache.org/jira/browse/CB-12465) Writing new JUnit Test Instrumentation to replace tests and retire problmatic tests
|
||||
|
||||
### 6.1.2 (Jan 26, 2017)
|
||||
* **Security** Change to `https` by default
|
||||
* [CB-12018](https://issues.apache.org/jira/browse/CB-12018): updated tests to work with jasmine (promise matcher tests commented out for now)
|
||||
* created directories and corresponding images for `xxhdpi` and `xxxhdpi`, both drawables and `mipmaps`
|
||||
|
||||
### 6.1.1 (Jan 03, 2017)
|
||||
* [CB-12159](https://issues.apache.org/jira/browse/CB-12159) **Android** Keystore password prompt won't show up
|
||||
* [CB-12169](https://issues.apache.org/jira/browse/CB-12169) Check for build directory before running a clean
|
||||
* Fixed `AndroidStudio` tests to actually run, removed `app/src/main/assets/` as a requirement and added `app/src/main/res` instead, added placeholder for `build/` folder, Removed dupe `gitignore`
|
||||
|
||||
### 6.1.0 (Nov 02, 2016)
|
||||
* [CB-12108](https://issues.apache.org/jira/browse/CB-12108) Updating gradle files to work with the latest version of Android Studio
|
||||
* [CB-12102](https://issues.apache.org/jira/browse/CB-12102) Bump travis to build to API 25
|
||||
* Bumping up the version
|
||||
* [CB-12101](https://issues.apache.org/jira/browse/CB-12101) Fix so that CLI builds don't conflict with Android Studio builds
|
||||
* [CB-12077](https://issues.apache.org/jira/browse/CB-12077) Fix paths for Android icons/splashscreens
|
||||
* added framework/build to .ratignore
|
||||
* Fix for broken testUrl test
|
||||
* Last minute change of test targets
|
||||
* Update JS snapshot to version 6.1.0-dev (via coho)
|
||||
* Set VERSION to 6.1.0-dev (via coho)
|
||||
|
||||
### 6.0.0 (Oct 20, 2016)
|
||||
|
||||
This release adds significant functionality, and also introduces a number
|
||||
of breaking changes. Some of the changes to the code base will be of
|
||||
particular interest to third party webview plugin developers.
|
||||
|
||||
#### Major Changes ####
|
||||
* Primary bridge is the EVAL_BRIDGE, which tells the WebView to execute JS directly. This is more stable than the ONLINE_EVENT bridge
|
||||
* Full Support for Android Nougat (API 24)
|
||||
* Ice Cream Sandwich Support has been deprecated. Minimum Supported Android Version is Jellybean (API 16/ Android 4.1)
|
||||
* Plugin Installation now CLEANS the build directory, this speeds up gradle build times and allows for CLI develoment to be more predictable
|
||||
|
||||
Changes For Third-Party WebView Developers:
|
||||
* executeJavascript method added and is an abstract method that must be implemented
|
||||
* the EVAL_BRIDGE must be added to the WebView
|
||||
|
||||
|
||||
#### Curated Changes from the Git Commit Logs ####
|
||||
* Updating the gradle build for test to use the latest
|
||||
* [CB-11083](https://issues.apache.org/jira/browse/CB-11083) Fixing syncronous file check and future-proofing the JS for Travis
|
||||
* [CB-11083](https://issues.apache.org/jira/browse/CB-11083) Reading files to check for CordovaLib dependency, if so, we exclude CordovaLib to be safe
|
||||
* [CB-11083](https://issues.apache.org/jira/browse/CB-11083) Plugin build script for dependencies without a gradle file
|
||||
* [CB-11083](https://issues.apache.org/jira/browse/CB-11083) The GradleBuidler can tell the difference between a Cordova Plugin Framework and a regular framework based on the name
|
||||
* [CB-11083](https://issues.apache.org/jira/browse/CB-11083) Fix to deal with custom frameworks with their own Gradle configuration
|
||||
* [CB-12003](https://issues.apache.org/jira/browse/CB-12003) updated node_modules
|
||||
* [CB-11771](https://issues.apache.org/jira/browse/CB-11771) Deep symlink directories to target project instead of linking the directory itself
|
||||
* [CB-11880](https://issues.apache.org/jira/browse/CB-11880) android: Fail-safe for cordova.exec()
|
||||
* [CB-11999](https://issues.apache.org/jira/browse/CB-11999) add message, catch exception if require fails
|
||||
* fix issue with app_name containing apostrophes
|
||||
* [CB-8722](https://issues.apache.org/jira/browse/CB-8722) - Move icons from drawable to mipmap
|
||||
* [CB-11964](https://issues.apache.org/jira/browse/CB-11964) Call clean after plugin install and mock it in tests
|
||||
* Did a try/catch to deal with the unit tests vs actual project environment, code duplication is needed because of builderEnv
|
||||
* [CB-11964](https://issues.apache.org/jira/browse/CB-11964) Do a clean when installing a plugin to et around the bug
|
||||
* [CB-11921](https://issues.apache.org/jira/browse/CB-11921) - Add github pull request template
|
||||
* [CB-11935](https://issues.apache.org/jira/browse/CB-11935) Does a best-effort attempt to pause any processing that can be paused safely, such as animations and geolocation.
|
||||
* [CB-11640](https://issues.apache.org/jira/browse/CB-11640) Fixing check_reqs.js so it actually works
|
||||
* [CB-11640](https://issues.apache.org/jira/browse/CB-11640) Changing requirements check to ask for Java 8
|
||||
* [CB-11869](https://issues.apache.org/jira/browse/CB-11869) Fix cordova-js android exec tests
|
||||
* [CB-11907](https://issues.apache.org/jira/browse/CB-11907) Bumping Gradle to work with Android Studio 2.2 and the Android Gradle Plugin
|
||||
* Enable background start of Cordova Android apps
|
||||
* fixing jshint issues
|
||||
* replace Integer.parseInt with BigInteger so that you can use longer Android version codes
|
||||
* [CB-11828](https://issues.apache.org/jira/browse/CB-11828) Adding dirty userAgent checking to see if we're running Jellybean or not for bridge modes
|
||||
* [CB-11828](https://issues.apache.org/jira/browse/CB-11828) Switching default bridge back to ONLINE_BRIDGE
|
||||
* Add gradle build flag to enable dex in process for large projects
|
||||
* added ability for cordova activity to be viewed in a real full screen regardless of android version (as was the case in previous cordova versions)
|
||||
* Updating travis
|
||||
* Adding Static Method to CoreAndroid Plugin so we can get the BuildConfig data from other plugins
|
||||
* Bump Target and Min API levels
|
||||
* Make evaluateJavaScript brige default
|
||||
* Creating an evaluateJavascript branch
|
||||
* [CB-11727](https://issues.apache.org/jira/browse/CB-11727) - travis ci setup is still using 0.10.32 node
|
||||
* [CB-11726](https://issues.apache.org/jira/browse/CB-11726) - Update appveyor node versions to 4 and 6, so they will always use the latest versions
|
||||
* Close invalid PRs
|
||||
* [CB-11683](https://issues.apache.org/jira/browse/CB-11683) Fixed linking to directories during plugin installation.
|
||||
* fixed [CB-11078](https://issues.apache.org/jira/browse/CB-11078) Empty string for BackgroundColor preference crashes application This closes #316
|
||||
* Update JS snapshot to version 5.3.0-dev (via coho)
|
||||
* Set VERSION to 5.3.0-dev (via coho)
|
||||
* [CB-11626](https://issues.apache.org/jira/browse/CB-11626) Updated RELEASENOTES and Version for release 5.2.2
|
||||
* updated cordoova-common to 1.4.0
|
||||
* This closes #195
|
||||
* Updaing the gradle for the tests to the latest
|
||||
* [CB-11550](https://issues.apache.org/jira/browse/CB-11550) Updated RELEASENOTES for release 5.2.1
|
||||
* [CB-9489](https://issues.apache.org/jira/browse/CB-9489) Fixed "endless waiting for emulator" issue
|
||||
* Update JS snapshot to version 5.3.0-dev (via coho)
|
||||
* Set VERSION to 5.3.0-dev (via coho)
|
||||
* [CB-11444](https://issues.apache.org/jira/browse/CB-11444) Updated RELEASENOTES and Version for release 5.2.0
|
||||
* [CB-11481](https://issues.apache.org/jira/browse/CB-11481) android-library is deprecated use com.android.library instead
|
||||
|
||||
### 5.2.2 (Jul 26, 2016)
|
||||
* [CB-11615](https://issues.apache.org/jira/browse/CB-11615) updated `cordoova-common` to `1.4.0`
|
||||
|
||||
### 5.2.1 (Jul 11, 2016)
|
||||
* [CB-9489](https://issues.apache.org/jira/browse/CB-9489) Fixed "endless waiting for emulator" issue
|
||||
* [CB-11481](https://issues.apache.org/jira/browse/CB-11481) android-library is deprecated use com.android.library instead
|
||||
|
||||
### 5.2.0 (Jun 29, 2016)
|
||||
* [CB-11383](https://issues.apache.org/jira/browse/CB-11383) Update to gradle for using `jcenter` and correct Application plugin
|
||||
* [CB-11365](https://issues.apache.org/jira/browse/CB-11365) fixed plugin rm issue with emit being `undefined`
|
||||
* [CB-11117](https://issues.apache.org/jira/browse/CB-11117) Use `FileUpdater` to optimize prepare for **android** platform
|
||||
* [CB-10096](https://issues.apache.org/jira/browse/CB-10096) Upgrade test project to `Gradle Plugin 2.1.0`
|
||||
* [CB-11292](https://issues.apache.org/jira/browse/CB-11292) fix broken `MessageChannel` after plugins are recreated
|
||||
* [CB-11259](https://issues.apache.org/jira/browse/CB-11259) Improving build output
|
||||
* [CB-10096](https://issues.apache.org/jira/browse/CB-10096) Upgrading to `Gradle Plugin 2.1.0`
|
||||
* [CB-11198](https://issues.apache.org/jira/browse/CB-11198) Skip **android** target sdk check. This closes #303.
|
||||
* [CB-11138](https://issues.apache.org/jira/browse/CB-11138) Reuse `PluginManager` from `common` to add/rm plugins
|
||||
* [CB-11133](https://issues.apache.org/jira/browse/CB-11133) Handle **android** emulator start failure
|
||||
* [CB-11132](https://issues.apache.org/jira/browse/CB-11132) Fix Error: Cannot read property `match` of undefined in `cordova-android` `emulator.js`
|
||||
* Add simple log for package name being deployed
|
||||
* [CB-11015](https://issues.apache.org/jira/browse/CB-11015) Error adding plugin with gradle extras
|
||||
* [CB-11095](https://issues.apache.org/jira/browse/CB-11095) Fix plugin add/removal when running on `Node v.010`
|
||||
* [CB-11022](https://issues.apache.org/jira/browse/CB-11022) Duplicate www files to both destinations on plugin operations
|
||||
* [CB-10964](https://issues.apache.org/jira/browse/CB-10964) Handle `build.json` file starting with a BOM.
|
||||
* [CB-10963](https://issues.apache.org/jira/browse/CB-10963) Handle overlapping permission requests from plugins
|
||||
* [CB-8582](https://issues.apache.org/jira/browse/CB-8582) Obscure `INSTALL_FAILED_VERSION_DOWNGRADE` error when installing app
|
||||
* [CB-10862](https://issues.apache.org/jira/browse/CB-10862) Cannot set `minsdkversion`
|
||||
* [CB-10896](https://issues.apache.org/jira/browse/CB-10896) We never enabled cookies on the `WebView` proper
|
||||
* [CB-10837](https://issues.apache.org/jira/browse/CB-10837) Support platform-specific orientation on **Android**
|
||||
* [CB-10600](https://issues.apache.org/jira/browse/CB-10600) `cordova run android --release` does not use signed and zip-aligned version of `APK`
|
||||
* [CB-9710](https://issues.apache.org/jira/browse/CB-9710) Fixing issues parsing `android avd list` output for certain AVDs which resulted in them not being included in the selection process even if they are the best match.
|
||||
* [CB-10888](https://issues.apache.org/jira/browse/CB-10888) Enable coverage reports collection via codecov
|
||||
* [CB-10846](https://issues.apache.org/jira/browse/CB-10846) Add Travis and AppVeyor badges to readme
|
||||
* [CB-10846](https://issues.apache.org/jira/browse/CB-10846) Add AppVeyor configuration
|
||||
* [CB-10749](https://issues.apache.org/jira/browse/CB-10749) Use `cordova-common.CordovaLogger` in `cordova-android`
|
||||
* [CB-10673](https://issues.apache.org/jira/browse/CB-10673) fixed conflicting plugin install issue with overlapped `<source-file>` tag. Add `--force` flag.
|
||||
* [CB-8976](https://issues.apache.org/jira/browse/CB-8976) Removing the auto-version for non-Crosswalk applications
|
||||
* [CB-10768](https://issues.apache.org/jira/browse/CB-10768) Use `cordova-common.superspawn` in `GradleBuilder`
|
||||
* [CB-10729](https://issues.apache.org/jira/browse/CB-10729) Move plugin handlers tests for into platform's repo
|
||||
* [CB-10669](https://issues.apache.org/jira/browse/CB-10669) `cordova run --list` cannot find `adb`
|
||||
* [CB-10660](https://issues.apache.org/jira/browse/CB-10660) fixed the exception when removing a non-existing directory.
|
||||
|
||||
### 5.1.1 (Feb 24, 2016)
|
||||
* updated `cordova-common` dependnecy to `1.1.0`
|
||||
* [CB-10628](https://issues.apache.org/jira/browse/CB-10628) Fix `emulate android --target`
|
||||
* [CB-10618](https://issues.apache.org/jira/browse/CB-10618) Handle gradle frameworks on plugin installation/uninstallation
|
||||
* [CB-10510](https://issues.apache.org/jira/browse/CB-10510) Add an optional timeout to `emu` start script
|
||||
* [CB-10498](https://issues.apache.org/jira/browse/CB-10498) Resume event should be sticky if it has a plugin result
|
||||
* fix `HtmlNotFoundTest` so that it passes when file not found is handled correctly
|
||||
* [CB-10472](https://issues.apache.org/jira/browse/CB-10472) `NullPointerException`: `org.apache.cordova.PluginManager.onSaveInstanceState` check if `pluginManager` is `null` before using it
|
||||
* [CB-10138](https://issues.apache.org/jira/browse/CB-10138) Adds missing plugin metadata to `plugin_list` module.
|
||||
* [CB-10443](https://issues.apache.org/jira/browse/CB-10443) Pass original options instead of remaining
|
||||
* [CB-10443](https://issues.apache.org/jira/browse/CB-10443) Fix `this.root` null reference
|
||||
* [CB-10421](https://issues.apache.org/jira/browse/CB-10421) Fixes exception when calling run script with `--help` option
|
||||
* updated `.gitignore`
|
||||
* [CB-10406](https://issues.apache.org/jira/browse/CB-10406) Fixes an exception, thrown when building using Ant.
|
||||
* [CB-10157](https://issues.apache.org/jira/browse/CB-10157) Uninstall app from device/emulator only when signed apk is already installed
|
||||
|
||||
### 5.1.0 (Jan 19, 2016)
|
||||
* [CB-10386](https://issues.apache.org/jira/browse/CB-10386) Add `android.useDeprecatedNdk=true` to support `NDK` in `gradle`
|
||||
* [CB-8864](https://issues.apache.org/jira/browse/CB-8864) Fixing this to mitigate [CB-8685](https://issues.apache.org/jira/browse/CB-8685) and [CB-10104](https://issues.apache.org/jira/browse/CB-10104)
|
||||
* [CB-10105](https://issues.apache.org/jira/browse/CB-10105) Spot fix for tilde errors on paths.
|
||||
* Update theme to `Theme.DeviceDefault.NoActionBar`
|
||||
* [CB-10014](https://issues.apache.org/jira/browse/CB-10014) Set gradle `applicationId` to `package name`.
|
||||
* [CB-9949](https://issues.apache.org/jira/browse/CB-9949) Fixing menu button event not fired in **Android**
|
||||
* [CB-9479](https://issues.apache.org/jira/browse/CB-9479) Fixing the conditionals again, we should
|
||||
* [CB-8917](https://issues.apache.org/jira/browse/CB-8917) New Plugin API for passing results on resume after Activity destruction
|
||||
* [CB-9971](https://issues.apache.org/jira/browse/CB-9971) Suppress `gradlew _JAVA_OPTIONS` output during build
|
||||
* [CB-9836](https://issues.apache.org/jira/browse/CB-9836) Add `.gitattributes` to prevent `CRLF` line endings in repos
|
||||
* added node_modules back into `.gitignore`
|
||||
|
||||
### 5.0.0 (Nov 01, 2015)
|
||||
* Update CordovaWebViewEngine.java
|
||||
* [CB-9909](https://issues.apache.org/jira/browse/CB-9909) Shouldn't escape spaces in paths on Windows.
|
||||
* [CB-9870](https://issues.apache.org/jira/browse/CB-9870) updated hello world template
|
||||
* [CB-9880](https://issues.apache.org/jira/browse/CB-9880) Fixes platform update failure when upgrading from android@<4.1.0
|
||||
* [CB-9844](https://issues.apache.org/jira/browse/CB-9844) Remove old .java after renaming activity
|
||||
* [CB-9800](https://issues.apache.org/jira/browse/CB-9800) Fixing contribute link.
|
||||
* [CB-9782](https://issues.apache.org/jira/browse/CB-9782) Check in `cordova-common` dependency
|
||||
* Adds licence header to Adb to pass rat audit
|
||||
* [CB-9835](https://issues.apache.org/jira/browse/CB-9835) Downgrade `properties-parser` to prevent failures in Node < 4.x
|
||||
* [CB-9782](https://issues.apache.org/jira/browse/CB-9782) Implements PlatformApi contract for Android platform.
|
||||
* [CB-9826](https://issues.apache.org/jira/browse/CB-9826) Fixed `test-build` script on windows.
|
||||
* Refactor of the Cordova Plugin/Permissions API
|
||||
* Manually updating version to 5.0.0-dev for engine tags
|
||||
* Bump up to API level 23
|
||||
* Commiting code to handle permissions, and the special case of the Geolocation Plugin
|
||||
* [CB-9608](https://issues.apache.org/jira/browse/CB-9608) cordova-android no longer builds on Node 0.10 or below
|
||||
* [CB-9080](https://issues.apache.org/jira/browse/CB-9080) Cordova CLI run for Android versions 4.1.1 and lower throws error
|
||||
* [CB-9557](https://issues.apache.org/jira/browse/CB-9557) Fixes apk install failure when switching from debug to release build
|
||||
* [CB-9496](https://issues.apache.org/jira/browse/CB-9496) removed permissions added for crosswalk
|
||||
* [CB-9402](https://issues.apache.org/jira/browse/CB-9402) Allow to set gradle distubutionUrl via env variable CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL
|
||||
* [CB-9428](https://issues.apache.org/jira/browse/CB-9428) update script now bumps up minSdkVersion to 14 if it is less than that.
|
||||
* [CB-9430](https://issues.apache.org/jira/browse/CB-9430) Fixes check_reqs failure when javac returns an extra line
|
||||
* [CB-9172](https://issues.apache.org/jira/browse/CB-9172) Improved emulator deploy stability. This closes #188.
|
||||
* [CB-9404](https://issues.apache.org/jira/browse/CB-9404) Fixed an exception when path contained -debug or -release
|
||||
* [CB-8320](https://issues.apache.org/jira/browse/CB-8320) Setting up gradle so we can use CordovaLib as a standard Android Library
|
||||
* [CB-9185](https://issues.apache.org/jira/browse/CB-9185) Fixed an issue when unsigned apks couldn't be found.
|
||||
* [CB-9397](https://issues.apache.org/jira/browse/CB-9397) Fixes minor issues with `cordova requirements android`
|
||||
* [CB-9389](https://issues.apache.org/jira/browse/CB-9389) Fixes build/check_reqs hang
|
||||
|
||||
### Release 4.1.1 (Aug 2015) ###
|
||||
|
||||
* [CB-9428](https://issues.apache.org/jira/browse/CB-9428) update script now bumps up minSdkVersion to 14 if it is less than that
|
||||
* [CB-9430](https://issues.apache.org/jira/browse/CB-9430) Fixes check_reqs failure when javac returns an extra line
|
||||
|
||||
### Release 4.1.0 (Jul 2015) ###
|
||||
* [CB-9392](https://issues.apache.org/jira/browse/CB-9392) Fixed printing flavored versions. This closes #184.
|
||||
* [CB-9382](https://issues.apache.org/jira/browse/CB-9382) [Android] Fix KeepRunning setting when Plugin activity is showed. This closes #200
|
||||
* [CB-9391](https://issues.apache.org/jira/browse/CB-9391) Fixes cdvBuildMultipleApks option casting
|
||||
* [CB-9343](https://issues.apache.org/jira/browse/CB-9343) Split the Content-Type to obtain a clean mimetype
|
||||
* [CB-9255](https://issues.apache.org/jira/browse/CB-9255) Make getUriType case insensitive.
|
||||
* [CB-9149](https://issues.apache.org/jira/browse/CB-9149) Fixes JSHint issue introduced by 899daa9
|
||||
* [CB-9372](https://issues.apache.org/jira/browse/CB-9372) Remove unused files: 'main.js' & 'master.css'. This closes #198
|
||||
* [CB-9149](https://issues.apache.org/jira/browse/CB-9149) Make gradle alias subprojects in order to handle libs that depend on libs. This closes #182
|
||||
* Update min SDK version to 14
|
||||
* Update licenses. This closes #190
|
||||
* [CB-9185](https://issues.apache.org/jira/browse/CB-9185) Fix signed release build exception. This closes #193.
|
||||
* [CB-9286](https://issues.apache.org/jira/browse/CB-9286) Fixes build failure when ANDROID_HOME is not set.
|
||||
* [CB-9284](https://issues.apache.org/jira/browse/CB-9284) Fix for handling absolute path for keystore in build.json
|
||||
* [CB-9260](https://issues.apache.org/jira/browse/CB-9260) Install Android-22 on Travis-CI
|
||||
* Adding .ratignore file.
|
||||
* [CB-9119](https://issues.apache.org/jira/browse/CB-9119) Adding lib/retry.js for retrying promise-returning functions. Retrying 'adb install' in emulator.js because it sometimes hangs.
|
||||
* [CB-9115](https://issues.apache.org/jira/browse/CB-9115) android: Grant Lollipop permission req
|
||||
* Remove extra console message
|
||||
* [CB-8898](https://issues.apache.org/jira/browse/CB-8898) Report expected gradle location properly
|
||||
* [CB-8898](https://issues.apache.org/jira/browse/CB-8898) Fixes gradle check failure due to missing quotes
|
||||
* [CB-9080](https://issues.apache.org/jira/browse/CB-9080) -d option is not supported on Android 4.1.1 and lower, removing
|
||||
* [CB-8954](https://issues.apache.org/jira/browse/CB-8954) Adds `requirements` command support to check_reqs module
|
||||
* Update JS snapshot to version 4.1.0-dev (via coho)
|
||||
* [CB-8417](https://issues.apache.org/jira/browse/CB-8417) updated platform specific files from cordova.js repo
|
||||
* Adding tests to confirm that preferences aren't changed by Intents
|
||||
* Forgot to remove the method that copied over the intent data
|
||||
* Getting around to removing this old Intent code
|
||||
* Update JS snapshot to version 4.1.0-dev (via coho)
|
||||
* Fix CordovaPluginTest on KitKat (start-up events seem to change)
|
||||
* [CB-3360](https://issues.apache.org/jira/browse/CB-3360) Allow setting a custom User-Agent (close #162)
|
||||
* [CB-8902](https://issues.apache.org/jira/browse/CB-8902) Use immersive mode when available when going fullscreen (close #175)
|
||||
* Make BridgeMode methods public (they were always supposed to be)
|
||||
* Simplify: EncodingUtils.getBytes(str) -> str.getBytes()
|
||||
* Don't show warning when gradlew file is read-only
|
||||
* Don't show warning when prepEnv copies gradlew and it's read-only
|
||||
* Make gradle wrapper prepEnv code work even when android-sdk is read-only
|
||||
* [CB-8897](https://issues.apache.org/jira/browse/CB-8897) Delete drawable/icon.png since it duplicates drawable-mdpi/icon.png
|
||||
* Updating the template to target mininumSdkTarget=14
|
||||
* [CB-8894](https://issues.apache.org/jira/browse/CB-8894) Updating the template to target mininumSdkTarget=14
|
||||
* [CB-8891](https://issues.apache.org/jira/browse/CB-8891) Add a note about when the gradle helpers were added
|
||||
* [CB-8891](https://issues.apache.org/jira/browse/CB-8891) Add a gradle helper for retrieving config.xml preference values
|
||||
* [CB-8884](https://issues.apache.org/jira/browse/CB-8884) Delete Eclipse tweaks from create script
|
||||
* [CB-8834](https://issues.apache.org/jira/browse/CB-8834) Don't fail to install on VERSION_DOWNGRADE
|
||||
* Automated tools fail, and you have to remember all four places where this is set.
|
||||
* Update the package.json
|
||||
* [CB-9042](https://issues.apache.org/jira/browse/CB-9042) coho failed to update version, so here we are
|
||||
* CB9042 - Updating Release Notes
|
||||
* Adding tests to confirm that preferences aren't changed by Intents
|
||||
* updating existing test code
|
||||
* Forgot to remove the method that copied over the intent data
|
||||
* Getting around to removing this old Intent code
|
||||
* [CB-8834](https://issues.apache.org/jira/browse/CB-8834) Don't fail to install on VERSION_DOWNGRADE
|
||||
|
||||
### Release 4.0.2 (May 2015) ###
|
||||
|
||||
* Removed Intent Functionality from Preferences - Preferences can no longer be set by intents
|
||||
|
||||
### Release 4.0.1 (April 2015) ###
|
||||
|
||||
* Bug fixed where platform failed to install on a version downgrade
|
||||
|
||||
### Release 4.0.0 (March 2015) ###
|
||||
|
||||
This release adds significant functionality, and also introduces a number
|
||||
of breaking changes. Some of the changes to the code base will be of
|
||||
particular interest to plugin developers.
|
||||
|
||||
#### Major Changes ####
|
||||
* Support for pluggable WebViews
|
||||
* The system WebView can be replaced in your app, via a plugin
|
||||
* Core WebView functionality is encapsulated, with extension points exposed
|
||||
via interfaces
|
||||
* Support for Crosswalk to bring the modern Chromium WebView to older devices
|
||||
* Uses the pluggable WebView framework
|
||||
* You will need to add the new [cordova-crosswalk-engine](https://github.com/MobileChromeApps/cordova-crosswalk-engine) plugin
|
||||
* Splash screen functionality is now provided via plugin
|
||||
* You will need to add the new [cordova-plugin-splashscreen](https://github.com/apache/cordova-plugin-splashscreen) plugin to continue using a splash screen
|
||||
* Whitelist functionality is now provided via plugin (CB-7747)
|
||||
* The whitelist has been enhanced to be more secure and configurable
|
||||
* Setting of Content-Security-Policy is now supported by the framework (see details in plugin readme)
|
||||
* You will need to add the new [cordova-plugin-whitelist](https://github.com/apache/cordova-plugin-whitelist) plugin
|
||||
* Legacy whitelist behaviour is still available via plugin (although not recommended).
|
||||
|
||||
Changes For Plugin Developers:
|
||||
|
||||
* Develop in Android Studio
|
||||
* Android Studio is now fully supported, and recommended over Eclipse
|
||||
* Build using Gradle
|
||||
* All builds [use Gradle by default](Android%20Shell%20Tool%20Guide_building_with_gradle), instead of Ant
|
||||
* Plugins can add their own gradle build steps!
|
||||
* Plugins can depend on Maven libraries using `<framework>` tags
|
||||
* New APIs: `onStart`, `onStop`, `onConfigurationChanged`
|
||||
* `"onScrollChanged"` message removed. Use `view.getViewTreeObserver().addOnScrollChangedListener(...)` instead
|
||||
* [CB-8702](https://issues.apache.org/jira/browse/CB-8702) New API for plugins to override `shouldInterceptRequest` with a stream
|
||||
|
||||
#### Other Changes ####
|
||||
* [CB-8378](https://issues.apache.org/jira/browse/CB-8378) Removed `hidekeyboard` and `showkeyboard` events (apps should use a plugin instead)
|
||||
* [CB-8735](https://issues.apache.org/jira/browse/CB-8735) `bin/create` regex relaxed / better support for numbers
|
||||
* [CB-8699](https://issues.apache.org/jira/browse/CB-8699) Fix CordovaResourceApi `copyResource` creating zero-length files when src=uncompressed asset
|
||||
* [CB-8693](https://issues.apache.org/jira/browse/CB-8693) CordovaLib should not contain icons / splashscreens
|
||||
* [CB-8592](https://issues.apache.org/jira/browse/CB-8592) Fix NPE if lifecycle events reach CordovaWebView before `init()` has been called
|
||||
* [CB-8588](https://issues.apache.org/jira/browse/CB-8588) Add CATEGORY_BROWSABLE to intents from showWebPage openExternal=true
|
||||
* [CB-8587](https://issues.apache.org/jira/browse/CB-8587) Don't allow WebView navigations within showWebPage that are not whitelisted
|
||||
* [CB-7827](https://issues.apache.org/jira/browse/CB-7827) Add `--activity-name` for `bin/create`
|
||||
* [CB-8548](https://issues.apache.org/jira/browse/CB-8548) Use debug-signing.properties and release-signing.properties when they exist
|
||||
* [CB-8545](https://issues.apache.org/jira/browse/CB-8545) Don't add a layout as a parent of the WebView
|
||||
* [CB-7159](https://issues.apache.org/jira/browse/CB-7159) BackgroundColor not used when `<html style="opacity:0">`, nor during screen rotation
|
||||
* [CB-6630](https://issues.apache.org/jira/browse/CB-6630) Removed OkHttp from core library. It's now available as a plugin: [cordova-plugin-okhttp](https://www.npmjs.com/package/cordova-plugin-okhttp)
|
||||
|
||||
### Release 3.7.1 (January 2015) ###
|
||||
* [CB-8411](https://issues.apache.org/jira/browse/CB-8411) Initialize plugins only after `createViews()` is called (regression in 3.7.0)
|
||||
|
||||
### Release 3.7.0 (January 2015) ###
|
||||
|
||||
* [CB-8328](https://issues.apache.org/jira/browse/CB-8328) Allow plugins to handle certificate challenges (close #150)
|
||||
* [CB-8201](https://issues.apache.org/jira/browse/CB-8201) Add support for auth dialogs into Cordova Android
|
||||
* [CB-8017](https://issues.apache.org/jira/browse/CB-8017) Add support for `<input type=file>` for Lollipop
|
||||
* [CB-8143](https://issues.apache.org/jira/browse/CB-8143) Loads of gradle improvements (try it with cordova/build --gradle)
|
||||
* [CB-8329](https://issues.apache.org/jira/browse/CB-8329) Cancel outstanding ActivityResult requests when a new startActivityForResult occurs
|
||||
* [CB-8026](https://issues.apache.org/jira/browse/CB-8026) Bumping up Android Version and setting it up to allow third-party cookies. This might change later.
|
||||
* [CB-8210](https://issues.apache.org/jira/browse/CB-8210) Use PluginResult for various events from native so that content-security-policy <meta> can be used
|
||||
* [CB-8168](https://issues.apache.org/jira/browse/CB-8168) Add support for `cordova/run --list` (closes #139)
|
||||
* [CB-8176](https://issues.apache.org/jira/browse/CB-8176) Vastly better auto-detection of SDK & JDK locations
|
||||
* [CB-8079](https://issues.apache.org/jira/browse/CB-8079) Use activity class package name, but fallback to application package name when looking for splash screen drawable
|
||||
* [CB-8147](https://issues.apache.org/jira/browse/CB-8147) Have corodva/build warn about unrecognized flags rather than fail
|
||||
* [CB-7881](https://issues.apache.org/jira/browse/CB-7881) Android tooling shouldn't lock application directory
|
||||
* [CB-8112](https://issues.apache.org/jira/browse/CB-8112) Turn off mediaPlaybackRequiresUserGesture
|
||||
* [CB-6153](https://issues.apache.org/jira/browse/CB-6153) Add a preference for controlling hardware button audio stream (DefaultVolumeStream)
|
||||
* [CB-8031](https://issues.apache.org/jira/browse/CB-8031) Fix race condition that shows as ConcurrentModificationException
|
||||
* [CB-7974](https://issues.apache.org/jira/browse/CB-7974) Cancel timeout timer if view is destroyed
|
||||
* [CB-7940](https://issues.apache.org/jira/browse/CB-7940) Disable exec bridge if bridgeSecret is wrong
|
||||
* [CB-7758](https://issues.apache.org/jira/browse/CB-7758) Allow content-url-hosted pages to access the bridge
|
||||
* [CB-6511](https://issues.apache.org/jira/browse/CB-6511) Fixes build for android when app name contains unicode characters.
|
||||
* [CB-7707](https://issues.apache.org/jira/browse/CB-7707) Added multipart PluginResult
|
||||
* [CB-6837](https://issues.apache.org/jira/browse/CB-6837) Fix leaked window when hitting back button while alert being rendered
|
||||
* [CB-7674](https://issues.apache.org/jira/browse/CB-7674) Move preference activation back into onCreate()
|
||||
* [CB-7499](https://issues.apache.org/jira/browse/CB-7499) Support RTL text direction
|
||||
* [CB-7330](https://issues.apache.org/jira/browse/CB-7330) Don't run check_reqs for bin/create.
|
||||
|
||||
### 3.6.4 (Sept 30, 2014) ###
|
||||
|
||||
* Set VERSION to 3.6.4 (via coho)
|
||||
* Update JS snapshot to version 3.6.4 (via coho)
|
||||
* [CB-7634](https://issues.apache.org/jira/browse/CB-7634) Detect JAVA_HOME properly on Ubuntu
|
||||
* [CB-7579](https://issues.apache.org/jira/browse/CB-7579) Fix run script's ability to use non-arch-specific APKs
|
||||
* [CB-6511](https://issues.apache.org/jira/browse/CB-6511) Fixes build for android when app name contains unicode characters.
|
||||
* [CB-7463](https://issues.apache.org/jira/browse/CB-7463) Adding licences. I don't know what the gradle syntax is for comments, that still needs to be done.
|
||||
* [CB-7463](https://issues.apache.org/jira/browse/CB-7463) Looked at the Apache BigTop git, gradle uses C-style comments
|
||||
* [CB-7460](https://issues.apache.org/jira/browse/CB-7460) Fixing bug with KitKat where the background colour would override the CSS colours on the application
|
||||
|
||||
### 3.6.0 (Sept 2014) ###
|
||||
|
||||
* Set VERSION to 3.6.0 (via coho)
|
||||
* [CB-7410](https://issues.apache.org/jira/browse/CB-7410) fix the menu test
|
||||
* [CB-7410](https://issues.apache.org/jira/browse/CB-7410) Fix the errorUrl test
|
||||
* [CB-7410](https://issues.apache.org/jira/browse/CB-7410) Fix Basic Authentication test
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Allow build and run scripts to select APK by architecture
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Add environment variable 'BUILD_MULTIPLE_APKS' for splitting APKs based on architecture
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Ensure that JAR files in libs directory are included
|
||||
* [CB-7267](https://issues.apache.org/jira/browse/CB-7267) update RELEASENOTES for 3.5.1
|
||||
* [CB-7410](https://issues.apache.org/jira/browse/CB-7410) clarify the title
|
||||
* [CB-7385](https://issues.apache.org/jira/browse/CB-7385) update cordova.js for testing prior to branch/tag
|
||||
* [CB-7410](https://issues.apache.org/jira/browse/CB-7410) add whitelist entries to get iframe/GoogleMaps working
|
||||
* [CB-7291](https://issues.apache.org/jira/browse/CB-7291) propogate change in method signature to the native tests
|
||||
* [CB-7291](https://issues.apache.org/jira/browse/CB-7291) Restrict meaning of "\*" in internal whitelist to just http and https
|
||||
* [CB-7291](https://issues.apache.org/jira/browse/CB-7291) Only add file, content and data URLs to internal whitelist
|
||||
* [CB-7291](https://issues.apache.org/jira/browse/CB-7291) Add defaults to external whitelist
|
||||
* [CB-7291](https://issues.apache.org/jira/browse/CB-7291) Add external-launch-whitelist and use it for filtering intent launches
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Read project.properties to configure gradle libraries
|
||||
* [CB-7325](https://issues.apache.org/jira/browse/CB-7325) Fix error message in android_sdk_version.js when missing SDK on windows
|
||||
* [CB-7335](https://issues.apache.org/jira/browse/CB-7335) Add a .gitignore to android project template
|
||||
* [CB-7330](https://issues.apache.org/jira/browse/CB-7330) Fix dangling function call in last commit (broke gradle builds)
|
||||
* [CB-7330](https://issues.apache.org/jira/browse/CB-7330) Don't run "android update" during creation
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Add gradle support clean command (plus some code cleanup)
|
||||
* [CB-7044](https://issues.apache.org/jira/browse/CB-7044) Fix typo in prev commit causing check_reqs to always fail.
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Copy gradle wrapper in build instead of create
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Add .gradle template files for "update" as well as "create"
|
||||
* [CB-7044](https://issues.apache.org/jira/browse/CB-7044) Add JAVA_HOME when not set. Be stricter about ANDROID_HOME
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Speed up gradle building (incremental builds go from 10s -> 1.5s for me)
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) android: Copy Gradle wrapper from Android SDK rather than bundling a JAR
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Add which to checked-in node_modules
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Add option to build and install with gradle
|
||||
* [CB-3445](https://issues.apache.org/jira/browse/CB-3445) Add an initial set of Gradle build scripts
|
||||
* [CB-7321](https://issues.apache.org/jira/browse/CB-7321) Don't require ant for create script
|
||||
* CB-7044, [CB-7299](https://issues.apache.org/jira/browse/CB-7299) Fix up PATH problems when possible.
|
||||
* Change in test's AndroidManifest.xml needed for the test to run properly. Forgot the manifest.
|
||||
* Change in test's AndroidManifest.xml needed for the test to run properly
|
||||
* Adding tests related to 3.5.1
|
||||
* [CB-7261](https://issues.apache.org/jira/browse/CB-7261) Fix setNativeToJsBridgeMode sometimes crashing when switching to ONLINE_EVENT
|
||||
* [CB-7265](https://issues.apache.org/jira/browse/CB-7265) Fix crash when navigating to custom protocol (introduced in 3.5.1)
|
||||
* Filter out non-launchable intents
|
||||
* Handle unsupported protocol errors in webview better
|
||||
* [CB-7238](https://issues.apache.org/jira/browse/CB-7238) I should have collapsed this, but Config.init() must go before the creation of CordovaWebView
|
||||
* [CB-7238](https://issues.apache.org/jira/browse/CB-7238) Minor band-aid to get tests running again, this has to go away before 3.6.0 is released, since this is an API change.
|
||||
* Extend whitelist to handle URLs without // chars
|
||||
* [CB-7172](https://issues.apache.org/jira/browse/CB-7172) Force window to have focus after resume
|
||||
* [CB-7159](https://issues.apache.org/jira/browse/CB-7159) Set background color of webView as well as its parent
|
||||
* [CB-7018](https://issues.apache.org/jira/browse/CB-7018) Fix setButtonPlumbedToJs never un-listening
|
||||
* Undeprecate some just-deprecated symbols in PluginManager.
|
||||
* @Deprecate methods of PluginManager that were never meant to be public
|
||||
* Move plugin instantiation and instance storing logic PluginEntry->PluginManager
|
||||
* Fix broken unit test due to missing Config.init() call
|
||||
* Update to check for Google Glass APIs
|
||||
* Fix for `android` not being in PATH check on Windows
|
||||
* Displaying error when regex does not match.
|
||||
* Fix broken compile due to previous commit :(
|
||||
* Tweak CordovaPlugin.initialize method to be less deprecated.
|
||||
* Un-deprecate CordovaActivity.init() - it's needed to tweak prefs in onCreate
|
||||
* Tweak log messages in CordovaBridge with bridgeSecret is wrong
|
||||
* Backport CordovaBridge from 4.0.x -> master
|
||||
* Update unit tests to not use most deprecated things (e.g. DroidGap)
|
||||
* Add non-String overloades for CordovaPreferences.set()
|
||||
* Make CordovaWebview resilient to init() not being called (for backwards-compatibility)
|
||||
* Add node_module licenses to LICENSE
|
||||
* Update cordova.js snapshot to work with bridge changes
|
||||
* Provide CordovaPlugin with CordovaPreferences. Add new Plugin.initialize()
|
||||
* Convert usages of Config.\* to use the non-static versions
|
||||
* Change getProperty -> prefs.get\* within CordovaActivity
|
||||
* Make CordovaUriHelper class package-private
|
||||
* Fix PluginManager.setPluginEntries not removing old entries
|
||||
* Move registration of App plugin from config.xml -> code
|
||||
* Make setWebViewClient an override instead of an overload. Delete Location-change JS->Native bridge mode (missed some of it).
|
||||
* [CB-4404](https://issues.apache.org/jira/browse/CB-4404) Revert setting android:windowSoftInputMode to "adjustPan"
|
||||
* Refactor: Use ConfigXmlParser in activity. Adds CordovaWebView.init()
|
||||
* Deprecate some convenience methods on CordovaActivity
|
||||
* Fix CordovaPreferences not correctly parsing hex values (valueOf->decode)
|
||||
* Refactor: Move url-filter information into PluginEntry.
|
||||
* Don't re-parse config.xml in onResume.
|
||||
* Move handling of Fullscreen preference to CordovaActivity
|
||||
* Delete dead code from CordovaActivity
|
||||
* Update .classpath to make Eclipse happy (just re-orders one line)
|
||||
* Delete "CB-3064: The errorUrl is..." Log message left over from debugging presumably
|
||||
* Refactor Config into ConfigXmlParser, CordovaPreferences
|
||||
* Delete Location-change JS->Native bridge mode
|
||||
* [CB-5988](https://issues.apache.org/jira/browse/CB-5988) Allow exec() only from file: or start-up URL's domain
|
||||
* [CB-6761](https://issues.apache.org/jira/browse/CB-6761) Fix native->JS bridge ceasing to fire when page changes and online is set to false and the JS loads quickly
|
||||
* Update the errorurl to no longer use intents
|
||||
* This breaks running the JUnit tests, we'll bring it back soon
|
||||
* Refactoring the URI handling on Cordova, removing dead code
|
||||
* [CB-7018](https://issues.apache.org/jira/browse/CB-7018) Clean up and deprecation of some button-related functions
|
||||
* [CB-7017](https://issues.apache.org/jira/browse/CB-7017) Fix onload=true being set on all subsequent plugins
|
||||
* [CB-5971](https://issues.apache.org/jira/browse/CB-5971) Fix package / project validation
|
||||
* [CB-5971](https://issues.apache.org/jira/browse/CB-5971) Add unit tests to cordova-android
|
||||
* [CB-5971](https://issues.apache.org/jira/browse/CB-5971) Factor out package/project name validation logic
|
||||
* Delete explicit activity.finish() in back button handling. No change in behaviour.
|
||||
* [CB-5971](https://issues.apache.org/jira/browse/CB-5971) This would have been a good first bug, too bad
|
||||
* [CB-4404](https://issues.apache.org/jira/browse/CB-4404) Changing where android:windowSoftInputMode is in the manifest so it works
|
||||
* Add documentation referencing other implementation.
|
||||
* [CB-6851](https://issues.apache.org/jira/browse/CB-6851) Deprecate WebView.sendJavascript()
|
||||
* [CB-6876](https://issues.apache.org/jira/browse/CB-6876) Show the correct executable name
|
||||
* [CB-6876](https://issues.apache.org/jira/browse/CB-6876) Fix the "print usage"
|
||||
* Trivial spelling fix in comments when reading CordovaResourceApi
|
||||
* [CB-6818](https://issues.apache.org/jira/browse/CB-6818) I want to remove this code, because Square didn't do their headers properly
|
||||
* [CB-6860](https://issues.apache.org/jira/browse/CB-6860) Add activity_name and launcher_name to AndroidManifest.xml & strings.xml
|
||||
* Add a comment to custom_rules.xml saying why we move AndroidManifest.xml
|
||||
* Remove +x from README.md
|
||||
* [CB-6784](https://issues.apache.org/jira/browse/CB-6784) Add missing licenses
|
||||
* [CB-6784](https://issues.apache.org/jira/browse/CB-6784) Add license to CONTRIBUTING.md
|
||||
* Revert "defaults.xml: Add AndroidLaunchMode preference"
|
||||
* updated RELEASENOTES
|
||||
* [CB-6315](https://issues.apache.org/jira/browse/CB-6315) Wrapping this so it runs on the UI thread
|
||||
* [CB-6723](https://issues.apache.org/jira/browse/CB-6723) Update package name for Robotium
|
||||
* [CB-6707](https://issues.apache.org/jira/browse/CB-6707) Update minSdkVersion to 10 consistently
|
||||
* [CB-5652](https://issues.apache.org/jira/browse/CB-5652) make visible cordova version
|
||||
* Update JS snapshot to version 3.6.0-dev (via coho)
|
||||
* Update JS snapshot to version 3.6.0-dev (via coho)
|
||||
* Set VERSION to 3.6.0-dev (via coho)
|
||||
|
||||
### 3.5.1 (August 2014) ###
|
||||
|
||||
This was a security update to address CVE-2014-3500, CVE-2014-3501,
|
||||
and CVE-2014-3502. For more information, see
|
||||
http://cordova.apache.org/announcements/2014/08/04/android-351.html
|
||||
|
||||
* Filter out non-launchable intents
|
||||
* Handle unsupported protocol errors in webview better
|
||||
* Update the errorurl to no longer use intents
|
||||
* Refactoring the URI handling on Cordova, removing dead code
|
||||
|
||||
### 3.5.0 (May 2014) ###
|
||||
|
||||
* OkHttp has broken headers. Updating for ASF compliance.
|
||||
* Revert accidentally removed lines from NOTICE
|
||||
* [CB-6552](https://issues.apache.org/jira/browse/CB-6552) added top level package.json
|
||||
* [CB-6491](https://issues.apache.org/jira/browse/CB-6491) add CONTRIBUTING.md
|
||||
* [CB-6543](https://issues.apache.org/jira/browse/CB-6543) Fix cordova/run failure when no custom_rules.xml available
|
||||
* defaults.xml: Add AndroidLaunchMode preference
|
||||
* Add JavaDoc for CordovaResourceApi
|
||||
* [CB-6388](https://issues.apache.org/jira/browse/CB-6388) Handle binary data correctly in LOAD_URL bridge
|
||||
* Fix [CB-6048](https://issues.apache.org/jira/browse/CB-6048) Set launchMode=singleTop so tapping app icon does not always restart app
|
||||
* Remove incorrect usage of AlertDialog.Builder.create
|
||||
* Catch uncaught exceptions in from plugins and turn them into error responses.
|
||||
* Add NOTICE file
|
||||
* [CB-6047](https://issues.apache.org/jira/browse/CB-6047) Fix online sometimes getting in a bad state on page transitions.
|
||||
* Add another convenience overload for CordovaResourceApi.copyResource
|
||||
* Update framework's .classpath to what Eclipse wants it to be.
|
||||
* README.md: `android update` to `android-19`.
|
||||
* Fix NPE when POLLING bridge mode is used.
|
||||
* Updating NOTICE to include Square for OkHttp
|
||||
* [CB-5398](https://issues.apache.org/jira/browse/CB-5398) Apply KitKat content URI fix to all content URIs
|
||||
* [CB-5398](https://issues.apache.org/jira/browse/CB-5398) Work-around for KitKat content: URLs not rendering in <img> tags
|
||||
* [CB-5908](https://issues.apache.org/jira/browse/CB-5908) add splascreen images to template
|
||||
* [CB-5395](https://issues.apache.org/jira/browse/CB-5395) Make scheme and host (but not path) case-insensitive in whitelist
|
||||
* Ignore multiple onPageFinished() callbacks & onReceivedError due to stopLoading()
|
||||
* Removing addJavascriptInterface support from all Android versions lower than 4.2 due to security vu
|
||||
* [CB-4984](https://issues.apache.org/jira/browse/CB-4984) Don't create on CordovaActivity name
|
||||
* [CB-5917](https://issues.apache.org/jira/browse/CB-5917) Add a loadUrlIntoView overload that doesn't recreate plugins.
|
||||
* Use thread pool for load timeout.
|
||||
* [CB-5715](https://issues.apache.org/jira/browse/CB-5715) For CLI, hide assets/www and res/xml/config.xml by default
|
||||
* [CB-5793](https://issues.apache.org/jira/browse/CB-5793) ant builds: Rename AndroidManifest during -post-build to avoid Eclipse detecting ant-build/
|
||||
* [CB-5889](https://issues.apache.org/jira/browse/CB-5889) Make update script find project name instead of using "null" for CordovaLib
|
||||
* [CB-5889](https://issues.apache.org/jira/browse/CB-5889) Add a message in the update script about needing to import CordovaLib when using an IDE.
|
||||
|
||||
### 3.4.0 (Feb 2014) ###
|
||||
|
||||
43 commits from 10 authors. Highlights include:
|
||||
|
||||
* Removing addJavascriptInterface support from all Android versions lower than 4.2 due to security vulnerability
|
||||
* [CB-5917](https://issues.apache.org/jira/browse/CB-5917) Add a loadUrlIntoView overload that doesn't recreate plugins.
|
||||
* [CB-5889](https://issues.apache.org/jira/browse/CB-5889) Make update script find project name instead of using "null" for CordovaLib
|
||||
* [CB-5889](https://issues.apache.org/jira/browse/CB-5889) Add a message in the update script about needing to import CordovaLib when using an IDE.
|
||||
* [CB-5793](https://issues.apache.org/jira/browse/CB-5793) Don't clean before build and change output directory to ant-build to avoid conflicts with Eclipse.
|
||||
* [CB-5803](https://issues.apache.org/jira/browse/CB-5803) Fix cordova/emulate on windows.
|
||||
* [CB-5801](https://issues.apache.org/jira/browse/CB-5801) exec->spawn in build to make sure compile errors are shown.
|
||||
* [CB-5799](https://issues.apache.org/jira/browse/CB-5799) Update version of OkHTTP to 1.3
|
||||
* [CB-4910](https://issues.apache.org/jira/browse/CB-4910) Update CLI project template to point to config.xml at the root now that it's not in www/ by default.
|
||||
* [CB-5504](https://issues.apache.org/jira/browse/CB-5504) Adding onDestroy to app plugin to deregister telephonyReceiver
|
||||
* [CB-5715](https://issues.apache.org/jira/browse/CB-5715) Add Eclipse .project file to create template. For CLI projects, it adds refs for root www/ & config.xml and hides platform versions
|
||||
* [CB-5447](https://issues.apache.org/jira/browse/CB-5447) Removed android:debuggable=“true” from project template.
|
||||
* [CB-5714](https://issues.apache.org/jira/browse/CB-5714) Fix of android build when too big output stops build with error due to buffer overflow.
|
||||
* [CB-5592](https://issues.apache.org/jira/browse/CB-5592) Set MIME type for openExternal when scheme is file:
|
||||
|
||||
### 3.3.0 (Dec 2013) ###
|
||||
|
||||
41 commits from 11 authors. Highlights include:
|
||||
|
||||
* [CB-5481](https://issues.apache.org/jira/browse/CB-5481) Fix for Cordova trying to get config.xml from the wrong namespace
|
||||
* [CB-5487](https://issues.apache.org/jira/browse/CB-5487) Enable Remote Debugging when your Android app is debuggable.
|
||||
* [CB-5445](https://issues.apache.org/jira/browse/CB-5445) Adding onScrollChanged and the ScrollEvent object
|
||||
* [CB-5422](https://issues.apache.org/jira/browse/CB-5422) Don't require JAVA_HOME to be defined
|
||||
* [CB-5490](https://issues.apache.org/jira/browse/CB-5490) Add javadoc target to ant script
|
||||
* [CB-5471](https://issues.apache.org/jira/browse/CB-5471) Deprecated DroidGap class
|
||||
* [CB-5255](https://issues.apache.org/jira/browse/CB-5255) Prefer Google API targets over android-## targets when building.
|
||||
* [CB-5232](https://issues.apache.org/jira/browse/CB-5232) Change create script to use Cordova as a Library Project instead of a .jar
|
||||
* [CB-5302](https://issues.apache.org/jira/browse/CB-5302) Massive movement to get tests working again
|
||||
* [CB-4996](https://issues.apache.org/jira/browse/CB-4996) Fix paths with spaces while launching on emulator and device
|
||||
* [CB-5209](https://issues.apache.org/jira/browse/CB-5209) Cannot build Android app if project path contains spaces
|
||||
|
||||
|
||||
### 3.2.0 (Nov 2013) ###
|
||||
|
||||
27 commits from 7 authors. Highlights include:
|
||||
|
||||
* [CB-5193](https://issues.apache.org/jira/browse/CB-5193) Fix Android WebSQL sometime throwing SECURITY_ERR.
|
||||
* [CB-5191](https://issues.apache.org/jira/browse/CB-5191) Deprecate <url-filter>
|
||||
* Updating shelljs to 0.2.6. Copy now preserves mode bits.
|
||||
* [CB-4872](https://issues.apache.org/jira/browse/CB-4872) Added android version scripts (android_sdk_version, etc)
|
||||
* [CB-5117](https://issues.apache.org/jira/browse/CB-5117) Output confirmation message if check_reqs passes.
|
||||
* [CB-5080](https://issues.apache.org/jira/browse/CB-5080) Find resources in a way that works with aapt's --rename-manifest-package
|
||||
* [CB-4527](https://issues.apache.org/jira/browse/CB-4527) Don't delete .bat files even when on non-windows platform
|
||||
* [CB-4892](https://issues.apache.org/jira/browse/CB-4892) Fix create script only escaping the first space instead of all spaces.
|
||||
|
||||
### 3.1.0 (Sept 2013) ###
|
||||
|
||||
55 commits from 9 authors. Highlights include:
|
||||
|
||||
* [CB-4817](https://issues.apache.org/jira/browse/CB-4817) Remove unused assets in project template.
|
||||
* Fail fast in create script if package name is not com.foo.bar.
|
||||
* [CB-4782](https://issues.apache.org/jira/browse/CB-4782) Convert ApplicationInfo.java -> appinfo.js
|
||||
* [CB-4766](https://issues.apache.org/jira/browse/CB-4766) Deprecated JSONUtils.java (moved into plugins)
|
||||
* [CB-4765](https://issues.apache.org/jira/browse/CB-4765) Deprecated ExifHelper.java (moved into plugins)
|
||||
* [CB-4764](https://issues.apache.org/jira/browse/CB-4764) Deprecated DirectoryManager.java (moved into plugins)
|
||||
* [CB-4763](https://issues.apache.org/jira/browse/CB-4763) Deprecated FileHelper.java (moved into plugins), Move getMimeType() into CordovaResourceApi.
|
||||
* [CB-4725](https://issues.apache.org/jira/browse/CB-4725) Add CordovaWebView.CORDOVA_VERSION constant
|
||||
* Incrementing version check for Android 4.3 API Level 18
|
||||
* [CB-3542](https://issues.apache.org/jira/browse/CB-3542) rewrote cli tooling scripts in node
|
||||
* Allow CordovaChromeClient subclasses access to CordovaInterface and CordovaWebView members
|
||||
* Refactor CordovaActivity.init so that subclasses can easily override factory methods for webview objects
|
||||
* [CB-4652](https://issues.apache.org/jira/browse/CB-4652) Allow default project template to be overridden on create
|
||||
* Tweak the online bridge to not send excess online events.
|
||||
* [CB-4495](https://issues.apache.org/jira/browse/CB-4495) Modify start-emulator script to exit immediately on a fatal emulator error.
|
||||
* Log WebView IOExceptions only when they are not 404s
|
||||
* Use a higher threshold for slow exec() warnings when debugger is attached.
|
||||
* Fix data URI decoding in CordovaResourceApi
|
||||
* [CB-3819](https://issues.apache.org/jira/browse/CB-3819) Made it easier to set SplashScreen delay.
|
||||
* [CB-4013](https://issues.apache.org/jira/browse/CB-4013) Fixed loadUrlTimeoutValue preference.
|
||||
* Upgrading project to Android 4.3
|
||||
* [CB-4198](https://issues.apache.org/jira/browse/CB-4198) bin/create script should be better at handling non-word characters in activity name. Patched windows script as well.
|
||||
* [CB-4198](https://issues.apache.org/jira/browse/CB-4198) bin/create should handle spaces in activity better.
|
||||
* [CB-4096](https://issues.apache.org/jira/browse/CB-4096) Implemented new unified whitelist for android
|
||||
* [CB-3384](https://issues.apache.org/jira/browse/CB-3384) Fix thread assertion when plugins remap URIs
|
||||
|
||||
21
bin/BOOM
@@ -1,21 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
#
|
||||
./bin/create
|
||||
cd ./example && ./cordova/debug && ./cordova/log
|
||||
115
bin/create
@@ -1,115 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# create a cordova/android project
|
||||
#
|
||||
# USAGE
|
||||
# ./create [path package activity]
|
||||
#
|
||||
set -e
|
||||
|
||||
if [ -n "$1" ] && [ "$1" == "-h" ]
|
||||
then
|
||||
echo 'usage: create path package activity'
|
||||
echo "Make sure the Android SDK tools folder is in your PATH!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
BUILD_PATH=$( cd "$( dirname "$0" )/.." && pwd )
|
||||
VERSION=$(cat $BUILD_PATH/VERSION)
|
||||
|
||||
PROJECT_PATH=${1:-"./example"}
|
||||
PACKAGE=${2:-"org.apache.cordova.example"}
|
||||
ACTIVITY=${3:-"cordovaExample"}
|
||||
|
||||
# clobber any existing example
|
||||
if [ -d $PROJECT_PATH ]
|
||||
then
|
||||
echo "Project already exists! Delete and recreate"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# cleanup after exit and/or on error
|
||||
function on_exit {
|
||||
echo "Cleaning up ..."
|
||||
# [ -f $BUILD_PATH/framework/libs/commons-codec-1.6.jar ] && rm $BUILD_PATH/framework/libs/commons-codec-1.6.jar
|
||||
# [ -d $BUILD_PATH/framework/libs ] && rmdir $BUILD_PATH/framework/libs
|
||||
[ -f $BUILD_PATH/framework/assets/www/cordova-$VERSION.js ] && rm $BUILD_PATH/framework/assets/www/cordova-$VERSION.js
|
||||
[ -f $BUILD_PATH/framework/cordova-$VERSION.jar ] && rm $BUILD_PATH/framework/cordova-$VERSION.jar
|
||||
}
|
||||
|
||||
function on_error {
|
||||
echo "An error occured. Deleting project..."
|
||||
[ -d $PROJECT_PATH ] && rm -rf $PROJECT_PATH
|
||||
}
|
||||
|
||||
# we do not want the script to silently fail
|
||||
trap on_error ERR
|
||||
trap on_exit EXIT
|
||||
|
||||
ANDROID_BIN=$( which android )
|
||||
PACKAGE_AS_PATH=$(echo $PACKAGE | sed 's/\./\//g')
|
||||
ACTIVITY_PATH=$PROJECT_PATH/src/$PACKAGE_AS_PATH/$ACTIVITY.java
|
||||
MANIFEST_PATH=$PROJECT_PATH/AndroidManifest.xml
|
||||
|
||||
TARGET=$($ANDROID_BIN list targets | grep id: | tail -1 | cut -f 2 -d ' ' )
|
||||
|
||||
# update the cordova-android framework for the desired target
|
||||
$ANDROID_BIN update project --target $TARGET --path $BUILD_PATH/framework &> /dev/null
|
||||
|
||||
if [ ! -e $BUILD_PATH/framework/libs/commons-codec-1.6.jar ]; then
|
||||
# Use curl to get the jar (TODO: Support Apache Mirrors)
|
||||
echo "Downloading common-codecs-1.6 ..."
|
||||
curl -OL http://mirror.symnds.com/software/Apache//commons/codec/binaries/commons-codec-1.6-bin.zip &> /dev/null
|
||||
unzip commons-codec-1.6-bin.zip &> /dev/null
|
||||
mkdir -p $BUILD_PATH/framework/libs
|
||||
cp commons-codec-1.6/commons-codec-1.6.jar $BUILD_PATH/framework/libs
|
||||
# cleanup yo
|
||||
rm commons-codec-1.6-bin.zip && rm -rf commons-codec-1.6
|
||||
fi
|
||||
|
||||
# compile cordova.js and cordova.jar
|
||||
echo "Building cordova-$VERSION.jar and cordova-$VERSION.js ..."
|
||||
(cd $BUILD_PATH/framework && ant jar &> /dev/null )
|
||||
|
||||
# create new android project
|
||||
echo "Creating a new cordova android project ..."
|
||||
$ANDROID_BIN create project --target $TARGET --path $PROJECT_PATH --package $PACKAGE --activity $ACTIVITY &> /dev/null
|
||||
|
||||
# copy project template
|
||||
echo "Copying assets and resources ..."
|
||||
cp -r $BUILD_PATH/bin/templates/project/assets $PROJECT_PATH
|
||||
cp -r $BUILD_PATH/bin/templates/project/res $PROJECT_PATH
|
||||
|
||||
# copy cordova.js, cordova.jar and res/xml
|
||||
echo "Setting up config and plugins list ..."
|
||||
cp -r $BUILD_PATH/framework/res/xml $PROJECT_PATH/res
|
||||
|
||||
echo "Adding cordova-$VERSION.js and cordova-$VERSION.jar ..."
|
||||
cp $BUILD_PATH/framework/assets/www/cordova-$VERSION.js $PROJECT_PATH/assets/www/cordova-$VERSION.js
|
||||
cp $BUILD_PATH/framework/cordova-$VERSION.jar $PROJECT_PATH/libs/cordova-$VERSION.jar
|
||||
|
||||
# interpolate the activity name and package
|
||||
echo "Updating Activity and AndroidManifest ..."
|
||||
cp $BUILD_PATH/bin/templates/project/Activity.java $ACTIVITY_PATH
|
||||
sed -i '' -e "s/__ACTIVITY__/${ACTIVITY}/g" $ACTIVITY_PATH
|
||||
sed -i '' -e "s/__ID__/${PACKAGE}/g" $ACTIVITY_PATH
|
||||
|
||||
cp $BUILD_PATH/bin/templates/project/AndroidManifest.xml $MANIFEST_PATH
|
||||
sed -i '' -e "s/__ACTIVITY__/${ACTIVITY}/g" $MANIFEST_PATH
|
||||
sed -i '' -e "s/__PACKAGE__/${PACKAGE}/g" $MANIFEST_PATH
|
||||
@@ -1,15 +0,0 @@
|
||||
@ECHO OFF
|
||||
IF NOT DEFINED JAVA_HOME GOTO MISSING
|
||||
FOR %%X in (java.exe ant.bat android.bat) do (
|
||||
SET FOUND=%%~$PATH:X
|
||||
IF NOT DEFINED FOUND GOTO MISSING
|
||||
)
|
||||
cscript %~dp0\create.js %*
|
||||
GOTO END
|
||||
:MISSING
|
||||
ECHO Missing one of the following:
|
||||
ECHO JDK: http://java.oracle.com
|
||||
ECHO Android SDK: http://developer.android.com
|
||||
ECHO Apache ant: http://ant.apache.org
|
||||
EXIT /B 1
|
||||
:END
|
||||
162
bin/create.js
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* create a cordova/android project
|
||||
*
|
||||
* USAGE
|
||||
* ./create [path package activity]
|
||||
*/
|
||||
|
||||
var fso = WScript.CreateObject('Scripting.FileSystemObject');
|
||||
|
||||
function read(filename) {
|
||||
var fso=WScript.CreateObject("Scripting.FileSystemObject");
|
||||
var f=fso.OpenTextFile(filename, 1);
|
||||
var s=f.ReadAll();
|
||||
f.Close();
|
||||
return s;
|
||||
}
|
||||
function write(filename, contents) {
|
||||
var fso=WScript.CreateObject("Scripting.FileSystemObject");
|
||||
var f=fso.OpenTextFile(filename, 2, true);
|
||||
f.Write(contents);
|
||||
f.Close();
|
||||
}
|
||||
function replaceInFile(filename, regexp, replacement) {
|
||||
write(filename, read(filename).replace(regexp, replacement));
|
||||
}
|
||||
function exec(s, output) {
|
||||
var o=shell.Exec(s);
|
||||
while (o.Status == 0) {
|
||||
WScript.Sleep(100);
|
||||
}
|
||||
//WScript.Echo("Command exited with code " + o.Status);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
// Cleanup
|
||||
// if(fso.FileExists(ROOT + '\\framework\\libs\\commons-codec-1.6.jar')) {
|
||||
// fso.DeleteFile(ROOT + '\\framework\\libs\\commons-codec-1.6.jar');
|
||||
// fso.DeleteFolder(ROOT + '\\framework\\libs', true);
|
||||
// }
|
||||
if(fso.FileExists(ROOT + '\\framework\\cordova-'+VERSION+'.jar')) {
|
||||
fso.DeleteFile(ROOT + '\\framework\\cordova-'+VERSION+'.jar');
|
||||
}
|
||||
if(fso.FileExists(ROOT + '\\framework\\assets\\www\\cordova-'+VERSION+'.js')) {
|
||||
fso.DeleteFile(ROOT + '\\framework\\assets\\www\\cordova-'+VERSION+'.js');
|
||||
}
|
||||
}
|
||||
|
||||
function downloadCommonsCodec() {
|
||||
if (!fso.FileExists(ROOT + '\\framework\\libs\\commons-codec-1.6.jar')) {
|
||||
// We need the .jar
|
||||
var url = 'http://mirror.symnds.com/software/Apache//commons/codec/binaries/commons-codec-1.6-bin.zip';
|
||||
var libsPath = ROOT + '\\framework\\libs';
|
||||
var savePath = libsPath + '\\commons-codec-1.6-bin.zip';
|
||||
if (!fso.FileExists(savePath)) {
|
||||
if(!fso.FolderExists(ROOT + '\\framework\\libs')) {
|
||||
fso.CreateFolder(libsPath);
|
||||
}
|
||||
// We need the zip to get the jar
|
||||
var xhr = WScript.CreateObject('MSXML2.XMLHTTP');
|
||||
xhr.open('GET', url, false);
|
||||
xhr.send();
|
||||
if (xhr.status == 200) {
|
||||
var stream = WScript.CreateObject('ADODB.Stream');
|
||||
stream.Open();
|
||||
stream.Type = 1;
|
||||
stream.Write(xhr.ResponseBody);
|
||||
stream.Position = 0;
|
||||
stream.SaveToFile(savePath);
|
||||
stream.Close();
|
||||
} else {
|
||||
WScript.Echo('Could not retrieve the commons-codec. Please download it yourself and put into the framework/libs directory. This process may fail now. Sorry.');
|
||||
}
|
||||
}
|
||||
var app = WScript.CreateObject('Shell.Application');
|
||||
var source = app.NameSpace(savePath).Items();
|
||||
var target = app.NameSpace(ROOT + '\\framework\\libs');
|
||||
target.CopyHere(source, 256);
|
||||
|
||||
// Move the jar into libs
|
||||
fso.MoveFile(ROOT + '\\framework\\libs\\commons-codec-1.6\\commons-codec-1.6.jar', ROOT + '\\framework\\libs\\commons-codec-1.6.jar');
|
||||
|
||||
// Clean up
|
||||
fso.DeleteFile(ROOT + '\\framework\\libs\\commons-codec-1.6-bin.zip');
|
||||
fso.DeleteFolder(ROOT + '\\framework\\libs\\commons-codec-1.6', true);
|
||||
}
|
||||
}
|
||||
|
||||
var args = WScript.Arguments, PROJECT_PATH="example",
|
||||
PACKAGE="org.apache.cordova.example", ACTIVITY="cordovaExample",
|
||||
shell=WScript.CreateObject("WScript.Shell");
|
||||
|
||||
// working dir
|
||||
var ROOT = WScript.ScriptFullName.split('\\bin\\create.js').join('');
|
||||
|
||||
if (args.Count() == 3) {
|
||||
PROJECT_PATH=args(0);
|
||||
PACKAGE=args(1);
|
||||
ACTIVITY=args(2);
|
||||
}
|
||||
|
||||
if(fso.FolderExists(PROJECT_PATH)) {
|
||||
WScript.Echo("Project already exists!");
|
||||
WScript.Quit(1);
|
||||
}
|
||||
|
||||
var PACKAGE_AS_PATH=PACKAGE.replace(/\./g, '\\');
|
||||
var ACTIVITY_PATH=PROJECT_PATH+'\\src\\'+PACKAGE_AS_PATH+'\\'+ACTIVITY+'.java';
|
||||
var MANIFEST_PATH=PROJECT_PATH+'\\AndroidManifest.xml';
|
||||
var TARGET=shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s([0-9]).*/)[1];
|
||||
var VERSION=read(ROOT+'\\VERSION').replace(/\r\n/,'').replace(/\n/,'');
|
||||
|
||||
// create the project
|
||||
exec('android.bat create project --target '+TARGET+' --path '+PROJECT_PATH+' --package '+PACKAGE+' --activity '+ACTIVITY);
|
||||
|
||||
// update the cordova framework project to a target that exists on this machine
|
||||
exec('android.bat update project --target '+TARGET+' --path '+ROOT+'\\framework');
|
||||
|
||||
// pull down commons codec if necessary
|
||||
downloadCommonsCodec();
|
||||
|
||||
exec('ant.bat -f '+ ROOT +'\\framework\\build.xml jar');
|
||||
|
||||
// copy in the project template
|
||||
exec('cmd /c xcopy '+ ROOT + '\\bin\\templates\\project\\* '+PROJECT_PATH+' /S /Y');
|
||||
|
||||
// copy in cordova.js
|
||||
exec('cmd /c copy '+ROOT+'\\framework\\assets\\www\\cordova-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\cordova-'+VERSION+'.js /Y');
|
||||
|
||||
// copy in cordova.jar
|
||||
exec('cmd /c copy '+ROOT+'\\framework\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y');
|
||||
|
||||
// copy in xml
|
||||
exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\cordova.xml ' + PROJECT_PATH + '\\res\\xml\\cordova.xml /Y');
|
||||
exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\plugins.xml ' + PROJECT_PATH + '\\res\\xml\\plugins.xml /Y');
|
||||
|
||||
// interpolate the activity name and package
|
||||
replaceInFile(ACTIVITY_PATH, /__ACTIVITY__/, ACTIVITY);
|
||||
replaceInFile(ACTIVITY_PATH, /__ID__/, PACKAGE);
|
||||
|
||||
replaceInFile(MANIFEST_PATH, /__ACTIVITY__/, ACTIVITY);
|
||||
replaceInFile(MANIFEST_PATH, /__PACKAGE__/, PACKAGE);
|
||||
|
||||
cleanup();
|
||||
@@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
<project name="cordova" default="create" basedir="../">
|
||||
|
||||
<property name="project.path" value="${basedir}/example"/>
|
||||
<property name="package" value="org.apache.cordova.example"/>
|
||||
<property name="activity" value="cordovaExample"/>
|
||||
|
||||
<target name="create">
|
||||
|
||||
<!-- this stuff is seriously stupid -->
|
||||
<echo file="tmp/package.tmp">package-as-path=${package}</echo>
|
||||
<replace file="tmp/package.tmp" token="." value="\\" />
|
||||
<property file="tmp/package.tmp" />
|
||||
|
||||
<property name="activity.path" value="${project.path}/src/${package-as-path}/${activity}.java" />
|
||||
<property name="manifest.path" value="${project.path}/AndroidManifest.xml" />
|
||||
|
||||
<!-- get the highest target on this machine -->
|
||||
<!-- this stuff is also seriously stupid -->
|
||||
<exec executable="cmd" osfamily="windows" output="tmp/target.list.tmp">
|
||||
<arg line="/c android.bat list targets"/>
|
||||
</exec>
|
||||
<exec executable="android" osfamily="mac" output="tmp/target.list.tmp">
|
||||
<arg line="list targets"/>
|
||||
</exec>
|
||||
<replaceregexp file="tmp/target.list.tmp" match=".*id:\s([0-9]).*" replace="target=\1" flags="s" />
|
||||
<property file="tmp/target.list.tmp" />
|
||||
|
||||
<!-- var VERSION=read('VERSION').replace(/\r\n/,'').replace(/\n/,''); -->
|
||||
<copy file="VERSION" tofile="tmp/VERSION.tmp" overwrite="true" />
|
||||
<replaceregexp file="tmp/VERSION.tmp" match="^" replace="version=" />
|
||||
<replaceregexp file="tmp/VERSION.tmp" match="\r\n" replace="" />
|
||||
<property file="tmp/VERSION.tmp" />
|
||||
|
||||
<!-- clobber any existing example -->
|
||||
|
||||
<!-- create the project -->
|
||||
<exec executable="cmd" osfamily="windows">
|
||||
<arg line="/c android.bat create project --target ${target} --path ${project.path} --package ${package} --activity ${activity}"/>
|
||||
</exec>
|
||||
<exec executable="android" osfamily="mac">
|
||||
<arg line="create project --target ${target} --path ${project.path} --package ${package} --activity ${activity}"/>
|
||||
</exec>
|
||||
|
||||
<!-- update the framework dir -->
|
||||
<exec executable="cmd" osfamily="windows">
|
||||
<arg line="/c android.bat update project --target ${target} --path ${basedir}/framework"/>
|
||||
</exec>
|
||||
<exec executable="android" osfamily="mac">
|
||||
<arg line="update project --target ${target} --path ${basedir}/framework"/>
|
||||
</exec>
|
||||
|
||||
<!-- compile cordova.js and cordova.jar -->
|
||||
<!-- // if you see an error about "Unable to resolve target" then you may need to
|
||||
// update your android tools or install an additional Android platform version -->
|
||||
<ant antfile="${basedir}/framework/build.xml" useNativeBasedir="true" inheritAll="false" />
|
||||
|
||||
<!-- copy in the project template -->
|
||||
<copy todir="${project.path}" overwrite="true">
|
||||
<fileset dir="${basedir}/bin/templates/project"/>
|
||||
</copy>
|
||||
|
||||
<!-- copy in cordova.js -->
|
||||
<copy file="${basedir}/framework/assets/www/cordova-${version}.js" todir="${project.path}/assets/www/" />
|
||||
|
||||
<!-- copy in cordova.jar -->
|
||||
<copy file="${basedir}/framework/cordova-${version}.jar" todir="${project.path}/libs/" />
|
||||
|
||||
<!-- copy in default activity -->
|
||||
<copy file="${basedir}/bin/templates/Activity.java" tofile="${activity.path}" overwrite="true" />
|
||||
|
||||
<!-- interpolate the activity name and package -->
|
||||
<replaceregexp file="${activity.path}" match="__ACTIVITY__" replace="${activity}" />
|
||||
<replaceregexp file="${activity.path}" match="__ID__" replace="${package}" />
|
||||
|
||||
<replaceregexp file="${manifest.path}" match="__ACTIVITY__" replace="${activity}" />
|
||||
<replaceregexp file="${manifest.path}" match="__PACKAGE__" replace="${package}" />
|
||||
</target>
|
||||
</project>
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "cordova-android-cli",
|
||||
"description": "CLI tooling for the cordova-android project",
|
||||
"version": "0.0.1",
|
||||
"licenses": [{
|
||||
"type": "APL 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
}],
|
||||
"main" : "./create",
|
||||
"bin": {
|
||||
"create": "./create",
|
||||
"bench": "./bench",
|
||||
"autotest": "./autotest",
|
||||
"BOOM": "./BOOM",
|
||||
"test": "./test"
|
||||
},
|
||||
"homepage": "http://incubator.apache.org/cordova",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://git-wip-us.apache.org/repos/asf/incubator-cordova-android.git"
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
|
||||
package="__PACKAGE__" android:versionName="1.1" android:versionCode="5">
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:smallScreens="true"
|
||||
android:xlargeScreens="true"
|
||||
android:resizeable="true"
|
||||
android:anyDensity="true"
|
||||
/>
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
|
||||
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name"
|
||||
android:debuggable="true">
|
||||
<activity android:name="__ACTIVITY__" android:label="@string/app_name"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<uses-sdk android:minSdkVersion="5" />
|
||||
</manifest>
|
||||
@@ -1,60 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=320; user-scalable=no" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<title>PhoneGap</title>
|
||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
|
||||
<script type="text/javascript" charset="utf-8" src="cordova-1.8.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
||||
|
||||
</head>
|
||||
<body onload="init();" id="stage" class="theme">
|
||||
<h1>Welcome to Cordova!</h1>
|
||||
<h2>this file is located at assets/www/index.html</h2>
|
||||
<div id="info">
|
||||
<h4>Platform: <span id="platform"> </span>, Version: <span id="version"> </span></h4>
|
||||
<h4>UUID: <span id="uuid"> </span>, Name: <span id="name"> </span></h4>
|
||||
<h4>Width: <span id="width"> </span>, Height: <span id="height">
|
||||
</span>, Color Depth: <span id="colorDepth"></span></h4>
|
||||
</div>
|
||||
<dl id="accel-data">
|
||||
<dt>X:</dt><dd id="x"> </dd>
|
||||
<dt>Y:</dt><dd id="y"> </dd>
|
||||
<dt>Z:</dt><dd id="z"> </dd>
|
||||
</dl>
|
||||
<a href="#" class="btn large" onclick="toggleAccel();">Toggle Accelerometer</a>
|
||||
<a href="#" class="btn large" onclick="getLocation();">Get Location</a>
|
||||
<a href="tel:411" class="btn large">Call 411</a>
|
||||
<a href="#" class="btn large" onclick="beep();">Beep</a>
|
||||
<a href="#" class="btn large" onclick="vibrate();">Vibrate</a>
|
||||
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
|
||||
<a href="#" class="btn large" onclick="get_contacts();return false;">Get Phone's Contacts</a>
|
||||
<a href="#" class="btn large" onclick="check_network();return false;">Check Network</a>
|
||||
<dl>
|
||||
<dt>Compass Heading:</dt><dd id="h">Off</dd>
|
||||
</dl>
|
||||
<a href="#" class="btn large" onclick="toggleCompass();return false;">Toggle Compass</a>
|
||||
<div id="viewport" class="viewport" style="display: none;">
|
||||
<img style="width:60px;height:60px" id="test_img" src="" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var deviceInfo = function() {
|
||||
document.getElementById("platform").innerHTML = device.platform;
|
||||
document.getElementById("version").innerHTML = device.version;
|
||||
document.getElementById("uuid").innerHTML = device.uuid;
|
||||
document.getElementById("name").innerHTML = device.name;
|
||||
document.getElementById("width").innerHTML = screen.width;
|
||||
document.getElementById("height").innerHTML = screen.height;
|
||||
document.getElementById("colorDepth").innerHTML = screen.colorDepth;
|
||||
};
|
||||
|
||||
var getLocation = function() {
|
||||
var suc = function(p) {
|
||||
alert(p.coords.latitude + " " + p.coords.longitude);
|
||||
};
|
||||
var locFail = function() {
|
||||
};
|
||||
navigator.geolocation.getCurrentPosition(suc, locFail);
|
||||
};
|
||||
|
||||
var beep = function() {
|
||||
navigator.notification.beep(2);
|
||||
};
|
||||
|
||||
var vibrate = function() {
|
||||
navigator.notification.vibrate(0);
|
||||
};
|
||||
|
||||
function roundNumber(num) {
|
||||
var dec = 3;
|
||||
var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
|
||||
return result;
|
||||
}
|
||||
|
||||
var accelerationWatch = null;
|
||||
|
||||
function updateAcceleration(a) {
|
||||
document.getElementById('x').innerHTML = roundNumber(a.x);
|
||||
document.getElementById('y').innerHTML = roundNumber(a.y);
|
||||
document.getElementById('z').innerHTML = roundNumber(a.z);
|
||||
}
|
||||
|
||||
var toggleAccel = function() {
|
||||
if (accelerationWatch !== null) {
|
||||
navigator.accelerometer.clearWatch(accelerationWatch);
|
||||
updateAcceleration({
|
||||
x : "",
|
||||
y : "",
|
||||
z : ""
|
||||
});
|
||||
accelerationWatch = null;
|
||||
} else {
|
||||
var options = {};
|
||||
options.frequency = 1000;
|
||||
accelerationWatch = navigator.accelerometer.watchAcceleration(
|
||||
updateAcceleration, function(ex) {
|
||||
alert("accel fail (" + ex.name + ": " + ex.message + ")");
|
||||
}, options);
|
||||
}
|
||||
};
|
||||
|
||||
var preventBehavior = function(e) {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
function dump_pic(data) {
|
||||
var viewport = document.getElementById('viewport');
|
||||
console.log(data);
|
||||
viewport.style.display = "";
|
||||
viewport.style.position = "absolute";
|
||||
viewport.style.top = "10px";
|
||||
viewport.style.left = "10px";
|
||||
document.getElementById("test_img").src = data;
|
||||
}
|
||||
|
||||
function fail(msg) {
|
||||
alert(msg);
|
||||
}
|
||||
|
||||
function show_pic() {
|
||||
navigator.camera.getPicture(dump_pic, fail, {
|
||||
quality : 50
|
||||
});
|
||||
}
|
||||
|
||||
function close() {
|
||||
var viewport = document.getElementById('viewport');
|
||||
viewport.style.position = "relative";
|
||||
viewport.style.display = "none";
|
||||
}
|
||||
|
||||
function contacts_success(contacts) {
|
||||
alert(contacts.length
|
||||
+ ' contacts returned.'
|
||||
+ (contacts[2] && contacts[2].name ? (' Third contact is ' + contacts[2].name.formatted)
|
||||
: ''));
|
||||
}
|
||||
|
||||
function get_contacts() {
|
||||
var obj = new ContactFindOptions();
|
||||
obj.filter = "";
|
||||
obj.multiple = true;
|
||||
navigator.contacts.find(
|
||||
[ "displayName", "name" ], contacts_success,
|
||||
fail, obj);
|
||||
}
|
||||
|
||||
function check_network() {
|
||||
var networkState = navigator.network.connection.type;
|
||||
|
||||
var states = {};
|
||||
states[Connection.UNKNOWN] = 'Unknown connection';
|
||||
states[Connection.ETHERNET] = 'Ethernet connection';
|
||||
states[Connection.WIFI] = 'WiFi connection';
|
||||
states[Connection.CELL_2G] = 'Cell 2G connection';
|
||||
states[Connection.CELL_3G] = 'Cell 3G connection';
|
||||
states[Connection.CELL_4G] = 'Cell 4G connection';
|
||||
states[Connection.NONE] = 'No network connection';
|
||||
|
||||
confirm('Connection type:\n ' + states[networkState]);
|
||||
}
|
||||
|
||||
var watchID = null;
|
||||
|
||||
function updateHeading(h) {
|
||||
document.getElementById('h').innerHTML = h.magneticHeading;
|
||||
}
|
||||
|
||||
function toggleCompass() {
|
||||
if (watchID !== null) {
|
||||
navigator.compass.clearWatch(watchID);
|
||||
watchID = null;
|
||||
updateHeading({ magneticHeading : "Off"});
|
||||
} else {
|
||||
var options = { frequency: 1000 };
|
||||
watchID = navigator.compass.watchHeading(updateHeading, function(e) {
|
||||
alert('Compass Error: ' + e.code);
|
||||
}, options);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
// the next line makes it impossible to see Contacts on the HTC Evo since it
|
||||
// doesn't have a scroll button
|
||||
// document.addEventListener("touchmove", preventBehavior, false);
|
||||
document.addEventListener("deviceready", deviceInfo, true);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
|
||||
body {
|
||||
background:#222 none repeat scroll 0 0;
|
||||
color:#666;
|
||||
font-family:Helvetica;
|
||||
font-size:72%;
|
||||
line-height:1.5em;
|
||||
margin:0;
|
||||
border-top:1px solid #393939;
|
||||
}
|
||||
|
||||
#info{
|
||||
background:#ffa;
|
||||
border: 1px solid #ffd324;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
clear:both;
|
||||
margin:15px 6px 0;
|
||||
width:295px;
|
||||
padding:4px 0px 2px 10px;
|
||||
}
|
||||
|
||||
#info > h4{
|
||||
font-size:.95em;
|
||||
margin:5px 0;
|
||||
}
|
||||
|
||||
#stage.theme{
|
||||
padding-top:3px;
|
||||
}
|
||||
|
||||
/* Definition List */
|
||||
#stage.theme > dl{
|
||||
padding-top:10px;
|
||||
clear:both;
|
||||
margin:0;
|
||||
list-style-type:none;
|
||||
padding-left:10px;
|
||||
overflow:auto;
|
||||
}
|
||||
|
||||
#stage.theme > dl > dt{
|
||||
font-weight:bold;
|
||||
float:left;
|
||||
margin-left:5px;
|
||||
}
|
||||
|
||||
#stage.theme > dl > dd{
|
||||
width:45px;
|
||||
float:left;
|
||||
color:#a87;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
/* Content Styling */
|
||||
#stage.theme > h1, #stage.theme > h2, #stage.theme > p{
|
||||
margin:1em 0 .5em 13px;
|
||||
}
|
||||
|
||||
#stage.theme > h1{
|
||||
color:#eee;
|
||||
font-size:1.6em;
|
||||
text-align:center;
|
||||
margin:0;
|
||||
margin-top:15px;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
#stage.theme > h2{
|
||||
clear:both;
|
||||
margin:0;
|
||||
padding:3px;
|
||||
font-size:1em;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
/* Stage Buttons */
|
||||
#stage.theme a.btn{
|
||||
border: 1px solid #555;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
text-align:center;
|
||||
display:block;
|
||||
float:left;
|
||||
background:#444;
|
||||
width:150px;
|
||||
color:#9ab;
|
||||
font-size:1.1em;
|
||||
text-decoration:none;
|
||||
padding:1.2em 0;
|
||||
margin:3px 0px 3px 5px;
|
||||
}
|
||||
#stage.theme a.btn.large{
|
||||
width:308px;
|
||||
padding:1.2em 0;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
@@ -1,100 +0,0 @@
|
||||
var build_path = __dirname + '/../..',
|
||||
project_path = '/tmp/example',
|
||||
package_name = 'org.apache.cordova.example',
|
||||
package_as_path = 'org/apache/cordova/example',
|
||||
project_name = 'cordovaExample';
|
||||
|
||||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
util = require('util'),
|
||||
assert = require('assert'),
|
||||
spawn = require('child_process').spawn;
|
||||
|
||||
var version = fs.readFileSync(build_path + '/VERSION').toString().replace('\n', '');
|
||||
|
||||
assert(version !== undefined);
|
||||
assert(version !== '');
|
||||
|
||||
var create_project = spawn(build_path + '/bin/create',
|
||||
[project_path,
|
||||
package_name,
|
||||
project_name]);
|
||||
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.log('Caught exception: ' + err);
|
||||
spawn('rm', ['-rf', project_path], function(code) {
|
||||
if(code != 0) {
|
||||
console.log("Could not delete project directory");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
create_project.on('exit', function(code) {
|
||||
|
||||
assert.equal(code, 0, 'Project did not get created');
|
||||
|
||||
// make sure the project was created
|
||||
path.exists(project_path, function(exists) {
|
||||
assert(exists, 'Project path does not exist');
|
||||
});
|
||||
|
||||
// make sure the build directory was cleaned up
|
||||
// path.exists(build_path + '/framework/libs', function(exists) {
|
||||
// assert(!exists, 'libs directory did not get cleaned up');
|
||||
// });
|
||||
path.exists(build_path + util.format('/framework/assets/cordova-%s.js', version), function(exists) {
|
||||
assert(!exists, 'javascript file did not get cleaned up');
|
||||
});
|
||||
path.exists(build_path + util.format('/framework/cordova-%s.jar', version), function(exists) {
|
||||
assert(!exists, 'jar file did not get cleaned up');
|
||||
});
|
||||
|
||||
// make sure AndroidManifest.xml was added
|
||||
path.exists(util.format('%s/AndroidManifest.xml', project_path), function(exists) {
|
||||
assert(exists, 'AndroidManifest.xml did not get created');
|
||||
// TODO check that the activity name was properly substituted
|
||||
});
|
||||
|
||||
// make sure main Activity was added
|
||||
path.exists(util.format('%s/src/%s/%s.java', project_path, package_as_path, project_name), function(exists) {
|
||||
assert(exists, 'Activity did not get created');
|
||||
// TODO check that package name and activity name were substitued properly
|
||||
});
|
||||
|
||||
// make sure plugins.xml was added
|
||||
path.exists(util.format('%s/res/xml/plugins.xml', project_path), function(exists) {
|
||||
assert(exists, 'plugins.xml did not get created');
|
||||
});
|
||||
|
||||
// make sure cordova.xml was added
|
||||
path.exists(util.format('%s/res/xml/cordova.xml', project_path), function(exists) {
|
||||
assert(exists, 'plugins.xml did not get created');
|
||||
});
|
||||
|
||||
// make sure cordova.jar was added
|
||||
path.exists(util.format('%s/libs/cordova-%s.jar', project_path, version), function(exists) {
|
||||
assert(exists, 'cordova.jar did not get added');
|
||||
});
|
||||
|
||||
// make sure cordova.js was added
|
||||
path.exists(util.format('%s/assets/www/cordova-%s.js', project_path, version), function(exists) {
|
||||
assert(exists, 'cordova.js did not get added');
|
||||
});
|
||||
|
||||
// check that project compiles && creates a cordovaExample-debug.apk
|
||||
var compile_project = spawn('ant', ['debug'], {cwd: project_path});
|
||||
|
||||
compile_project.on('exit', function(code) {
|
||||
assert.equal(code, 0, 'Cordova Android Project does not compile');
|
||||
// make sure cordovaExample-debug.apk was created
|
||||
path.exists(util.format('%s/bin/%s-debug.apk', project_path, project_name), function(exists) {
|
||||
assert(exists, 'Package did not get created');
|
||||
|
||||
// if project compiles properly just AXE it
|
||||
spawn('rm', ['-rf', project_path], function(code) {
|
||||
assert.equal(code, 0, 'Could not remove project directory');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
36
cordova-js-src/android/nativeapiprovider.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
|
||||
*/
|
||||
|
||||
var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
|
||||
var currentApi = nativeApi;
|
||||
|
||||
module.exports = {
|
||||
get: function () { return currentApi; },
|
||||
setPreferPrompt: function (value) {
|
||||
currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
|
||||
},
|
||||
// Used only by tests.
|
||||
set: function (value) {
|
||||
currentApi = value;
|
||||
}
|
||||
};
|
||||
35
cordova-js-src/android/promptbasednativeapi.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
|
||||
* This is used pre-JellyBean, where addJavascriptInterface() is disabled.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
exec: function (bridgeSecret, service, action, callbackId, argsJson) {
|
||||
return prompt(argsJson, 'gap:' + JSON.stringify([bridgeSecret, service, action, callbackId]));
|
||||
},
|
||||
setNativeToJsBridgeMode: function (bridgeSecret, value) {
|
||||
prompt(value, 'gap_bridge_mode:' + bridgeSecret);
|
||||
},
|
||||
retrieveJsMessages: function (bridgeSecret, fromOnlineEvent) {
|
||||
return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
|
||||
}
|
||||
};
|
||||
287
cordova-js-src/exec.js
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Execute a cordova command. It is up to the native side whether this action
|
||||
* is synchronous or asynchronous. The native side can return:
|
||||
* Synchronous: PluginResult object as a JSON string
|
||||
* Asynchronous: Empty string ""
|
||||
* If async, the native side will cordova.callbackSuccess or cordova.callbackError,
|
||||
* depending upon the result of the action.
|
||||
*
|
||||
* @param {Function} success The success callback
|
||||
* @param {Function} fail The fail callback
|
||||
* @param {String} service The name of the service to use
|
||||
* @param {String} action Action to be run in cordova
|
||||
* @param {String[]} [args] Zero or more arguments to pass to the method
|
||||
*/
|
||||
var cordova = require('cordova');
|
||||
var nativeApiProvider = require('cordova/android/nativeapiprovider');
|
||||
var utils = require('cordova/utils');
|
||||
var base64 = require('cordova/base64');
|
||||
var channel = require('cordova/channel');
|
||||
var jsToNativeModes = {
|
||||
PROMPT: 0,
|
||||
JS_OBJECT: 1
|
||||
};
|
||||
var nativeToJsModes = {
|
||||
// Polls for messages using the JS->Native bridge.
|
||||
POLLING: 0,
|
||||
// For LOAD_URL to be viable, it would need to have a work-around for
|
||||
// the bug where the soft-keyboard gets dismissed when a message is sent.
|
||||
LOAD_URL: 1,
|
||||
// For the ONLINE_EVENT to be viable, it would need to intercept all event
|
||||
// listeners (both through addEventListener and window.ononline) as well
|
||||
// as set the navigator property itself.
|
||||
ONLINE_EVENT: 2,
|
||||
EVAL_BRIDGE: 3
|
||||
};
|
||||
var jsToNativeBridgeMode; // Set lazily.
|
||||
var nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE;
|
||||
var pollEnabled = false;
|
||||
var bridgeSecret = -1;
|
||||
|
||||
var messagesFromNative = [];
|
||||
var isProcessing = false;
|
||||
var resolvedPromise = typeof Promise === 'undefined' ? null : Promise.resolve();
|
||||
var nextTick = resolvedPromise ? function (fn) { resolvedPromise.then(fn); } : function (fn) { setTimeout(fn); };
|
||||
|
||||
function androidExec (success, fail, service, action, args) {
|
||||
if (bridgeSecret < 0) {
|
||||
// If we ever catch this firing, we'll need to queue up exec()s
|
||||
// and fire them once we get a secret. For now, I don't think
|
||||
// it's possible for exec() to be called since plugins are parsed but
|
||||
// not run until until after onNativeReady.
|
||||
throw new Error('exec() called without bridgeSecret');
|
||||
}
|
||||
// Set default bridge modes if they have not already been set.
|
||||
// By default, we use the failsafe, since addJavascriptInterface breaks too often
|
||||
if (jsToNativeBridgeMode === undefined) {
|
||||
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
|
||||
}
|
||||
|
||||
// If args is not provided, default to an empty array
|
||||
args = args || [];
|
||||
|
||||
// Process any ArrayBuffers in the args into a string.
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
if (utils.typeName(args[i]) === 'ArrayBuffer') {
|
||||
args[i] = base64.fromArrayBuffer(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var callbackId = service + cordova.callbackId++;
|
||||
var argsJson = JSON.stringify(args);
|
||||
if (success || fail) {
|
||||
cordova.callbacks[callbackId] = { success: success, fail: fail };
|
||||
}
|
||||
|
||||
var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
|
||||
// If argsJson was received by Java as null, try again with the PROMPT bridge mode.
|
||||
// This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
|
||||
if (jsToNativeBridgeMode === jsToNativeModes.JS_OBJECT && msgs === '@Null arguments.') {
|
||||
androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
|
||||
androidExec(success, fail, service, action, args);
|
||||
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
|
||||
} else if (msgs) {
|
||||
messagesFromNative.push(msgs);
|
||||
// Always process async to avoid exceptions messing up stack.
|
||||
nextTick(processMessages);
|
||||
}
|
||||
}
|
||||
|
||||
androidExec.init = function () {
|
||||
bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
|
||||
channel.onNativeReady.fire();
|
||||
};
|
||||
|
||||
function pollOnceFromOnlineEvent () {
|
||||
pollOnce(true);
|
||||
}
|
||||
|
||||
function pollOnce (opt_fromOnlineEvent) {
|
||||
if (bridgeSecret < 0) {
|
||||
// This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
|
||||
// We know there's nothing to retrieve, so no need to poll.
|
||||
return;
|
||||
}
|
||||
var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
|
||||
if (msgs) {
|
||||
messagesFromNative.push(msgs);
|
||||
// Process sync since we know we're already top-of-stack.
|
||||
processMessages();
|
||||
}
|
||||
}
|
||||
|
||||
function pollingTimerFunc () {
|
||||
if (pollEnabled) {
|
||||
pollOnce();
|
||||
setTimeout(pollingTimerFunc, 50);
|
||||
}
|
||||
}
|
||||
|
||||
function hookOnlineApis () {
|
||||
function proxyEvent (e) {
|
||||
cordova.fireWindowEvent(e.type);
|
||||
}
|
||||
// The network module takes care of firing online and offline events.
|
||||
// It currently fires them only on document though, so we bridge them
|
||||
// to window here (while first listening for exec()-releated online/offline
|
||||
// events).
|
||||
window.addEventListener('online', pollOnceFromOnlineEvent, false);
|
||||
window.addEventListener('offline', pollOnceFromOnlineEvent, false);
|
||||
cordova.addWindowEventHandler('online');
|
||||
cordova.addWindowEventHandler('offline');
|
||||
document.addEventListener('online', proxyEvent, false);
|
||||
document.addEventListener('offline', proxyEvent, false);
|
||||
}
|
||||
|
||||
hookOnlineApis();
|
||||
|
||||
androidExec.jsToNativeModes = jsToNativeModes;
|
||||
androidExec.nativeToJsModes = nativeToJsModes;
|
||||
|
||||
androidExec.setJsToNativeBridgeMode = function (mode) {
|
||||
if (mode === jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
|
||||
mode = jsToNativeModes.PROMPT;
|
||||
}
|
||||
nativeApiProvider.setPreferPrompt(mode === jsToNativeModes.PROMPT);
|
||||
jsToNativeBridgeMode = mode;
|
||||
};
|
||||
|
||||
androidExec.setNativeToJsBridgeMode = function (mode) {
|
||||
if (mode === nativeToJsBridgeMode) {
|
||||
return;
|
||||
}
|
||||
if (nativeToJsBridgeMode === nativeToJsModes.POLLING) {
|
||||
pollEnabled = false;
|
||||
}
|
||||
|
||||
nativeToJsBridgeMode = mode;
|
||||
// Tell the native side to switch modes.
|
||||
// Otherwise, it will be set by androidExec.init()
|
||||
if (bridgeSecret >= 0) {
|
||||
nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
|
||||
}
|
||||
|
||||
if (mode === nativeToJsModes.POLLING) {
|
||||
pollEnabled = true;
|
||||
setTimeout(pollingTimerFunc, 1);
|
||||
}
|
||||
};
|
||||
|
||||
function buildPayload (payload, message) {
|
||||
var payloadKind = message.charAt(0);
|
||||
if (payloadKind === 's') {
|
||||
payload.push(message.slice(1));
|
||||
} else if (payloadKind === 't') {
|
||||
payload.push(true);
|
||||
} else if (payloadKind === 'f') {
|
||||
payload.push(false);
|
||||
} else if (payloadKind === 'N') {
|
||||
payload.push(null);
|
||||
} else if (payloadKind === 'n') {
|
||||
payload.push(+message.slice(1));
|
||||
} else if (payloadKind === 'A') {
|
||||
var data = message.slice(1);
|
||||
payload.push(base64.toArrayBuffer(data));
|
||||
} else if (payloadKind === 'S') {
|
||||
payload.push(window.atob(message.slice(1)));
|
||||
} else if (payloadKind === 'M') {
|
||||
var multipartMessages = message.slice(1);
|
||||
while (multipartMessages !== '') {
|
||||
var spaceIdx = multipartMessages.indexOf(' ');
|
||||
var msgLen = +multipartMessages.slice(0, spaceIdx);
|
||||
var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
|
||||
multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
|
||||
buildPayload(payload, multipartMessage);
|
||||
}
|
||||
} else {
|
||||
payload.push(JSON.parse(message));
|
||||
}
|
||||
}
|
||||
|
||||
// Processes a single message, as encoded by NativeToJsMessageQueue.java.
|
||||
function processMessage (message) {
|
||||
var firstChar = message.charAt(0);
|
||||
if (firstChar === 'J') {
|
||||
// This is deprecated on the .java side. It doesn't work with CSP enabled.
|
||||
// eslint-disable-next-line no-eval
|
||||
eval(message.slice(1));
|
||||
} else if (firstChar === 'S' || firstChar === 'F') {
|
||||
var success = firstChar === 'S';
|
||||
var keepCallback = message.charAt(1) === '1';
|
||||
var spaceIdx = message.indexOf(' ', 2);
|
||||
var status = +message.slice(2, spaceIdx);
|
||||
var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
|
||||
var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
|
||||
var payloadMessage = message.slice(nextSpaceIdx + 1);
|
||||
var payload = [];
|
||||
buildPayload(payload, payloadMessage);
|
||||
cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
|
||||
} else {
|
||||
console.log('processMessage failed: invalid message: ' + JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
|
||||
function processMessages () {
|
||||
// Check for the reentrant case.
|
||||
if (isProcessing) {
|
||||
return;
|
||||
}
|
||||
if (messagesFromNative.length === 0) {
|
||||
return;
|
||||
}
|
||||
isProcessing = true;
|
||||
try {
|
||||
var msg = popMessageFromQueue();
|
||||
// The Java side can send a * message to indicate that it
|
||||
// still has messages waiting to be retrieved.
|
||||
if (msg === '*' && messagesFromNative.length === 0) {
|
||||
nextTick(pollOnce);
|
||||
return;
|
||||
}
|
||||
processMessage(msg);
|
||||
} finally {
|
||||
isProcessing = false;
|
||||
if (messagesFromNative.length > 0) {
|
||||
nextTick(processMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function popMessageFromQueue () {
|
||||
var messageBatch = messagesFromNative.shift();
|
||||
if (messageBatch === '*') {
|
||||
return '*';
|
||||
}
|
||||
|
||||
var spaceIdx = messageBatch.indexOf(' ');
|
||||
var msgLen = +messageBatch.slice(0, spaceIdx);
|
||||
var message = messageBatch.substr(spaceIdx + 1, msgLen);
|
||||
messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
|
||||
if (messageBatch) {
|
||||
messagesFromNative.unshift(messageBatch);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
module.exports = androidExec;
|
||||
122
cordova-js-src/platform.js
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// The last resume event that was received that had the result of a plugin call.
|
||||
var lastResumeEvent = null;
|
||||
|
||||
module.exports = {
|
||||
id: 'android',
|
||||
bootstrap: function () {
|
||||
var channel = require('cordova/channel');
|
||||
var cordova = require('cordova');
|
||||
var exec = require('cordova/exec');
|
||||
var modulemapper = require('cordova/modulemapper');
|
||||
|
||||
// Get the shared secret needed to use the bridge.
|
||||
exec.init();
|
||||
|
||||
// TODO: Extract this as a proper plugin.
|
||||
modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
|
||||
|
||||
var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
|
||||
|
||||
// Inject a listener for the backbutton on the document.
|
||||
var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
|
||||
backButtonChannel.onHasSubscribersChange = function () {
|
||||
// If we just attached the first handler or detached the last handler,
|
||||
// let native know we need to override the back button.
|
||||
exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [this.numHandlers === 1]);
|
||||
};
|
||||
|
||||
// Add hardware MENU and SEARCH button handlers
|
||||
cordova.addDocumentEventHandler('menubutton');
|
||||
cordova.addDocumentEventHandler('searchbutton');
|
||||
|
||||
function bindButtonChannel (buttonName) {
|
||||
// generic button bind used for volumeup/volumedown buttons
|
||||
var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
|
||||
volumeButtonChannel.onHasSubscribersChange = function () {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [buttonName, this.numHandlers === 1]);
|
||||
};
|
||||
}
|
||||
// Inject a listener for the volume buttons on the document.
|
||||
bindButtonChannel('volumeup');
|
||||
bindButtonChannel('volumedown');
|
||||
|
||||
// The resume event is not "sticky", but it is possible that the event
|
||||
// will contain the result of a plugin call. We need to ensure that the
|
||||
// plugin result is delivered even after the event is fired (CB-10498)
|
||||
var cordovaAddEventListener = document.addEventListener;
|
||||
|
||||
document.addEventListener = function (evt, handler, capture) {
|
||||
cordovaAddEventListener(evt, handler, capture);
|
||||
|
||||
if (evt === 'resume' && lastResumeEvent) {
|
||||
handler(lastResumeEvent);
|
||||
}
|
||||
};
|
||||
|
||||
// Let native code know we are all done on the JS side.
|
||||
// Native code will then un-hide the WebView.
|
||||
channel.onCordovaReady.subscribe(function () {
|
||||
exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
|
||||
exec(null, null, APP_PLUGIN_NAME, 'show', []);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function onMessageFromNative (msg) {
|
||||
var cordova = require('cordova');
|
||||
var action = msg.action;
|
||||
|
||||
switch (action) {
|
||||
// pause and resume are Android app life cycle events
|
||||
case 'backbutton':
|
||||
case 'menubutton':
|
||||
case 'searchbutton':
|
||||
case 'pause':
|
||||
case 'volumedownbutton':
|
||||
case 'volumeupbutton':
|
||||
cordova.fireDocumentEvent(action);
|
||||
break;
|
||||
case 'resume':
|
||||
if (arguments.length > 1 && msg.pendingResult) {
|
||||
if (arguments.length === 2) {
|
||||
msg.pendingResult.result = arguments[1];
|
||||
} else {
|
||||
// The plugin returned a multipart message
|
||||
var res = [];
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
res.push(arguments[i]);
|
||||
}
|
||||
msg.pendingResult.result = res;
|
||||
}
|
||||
|
||||
// Save the plugin result so that it can be delivered to the js
|
||||
// even if they miss the initial firing of the event
|
||||
lastResumeEvent = msg;
|
||||
}
|
||||
cordova.fireDocumentEvent(action, msg);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown event action ' + action);
|
||||
}
|
||||
}
|
||||
108
cordova-js-src/plugin/android/app.js
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Clear the resource cache.
|
||||
*/
|
||||
clearCache: function () {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'clearCache', []);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the url into the webview or into new browser instance.
|
||||
*
|
||||
* @param url The URL to load
|
||||
* @param props Properties that can be passed in to the activity:
|
||||
* wait: int => wait msec before loading URL
|
||||
* loadingDialog: "Title,Message" => display a native loading dialog
|
||||
* loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
|
||||
* clearHistory: boolean => clear webview history (default=false)
|
||||
* openExternal: boolean => open in a new browser (default=false)
|
||||
*
|
||||
* Example:
|
||||
* navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
|
||||
*/
|
||||
loadUrl: function (url, props) {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'loadUrl', [url, props]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Cancel loadUrl that is waiting to be loaded.
|
||||
*/
|
||||
cancelLoadUrl: function () {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'cancelLoadUrl', []);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear web history in this web view.
|
||||
* Instead of BACK button loading the previous web page, it will exit the app.
|
||||
*/
|
||||
clearHistory: function () {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'clearHistory', []);
|
||||
},
|
||||
|
||||
/**
|
||||
* Go to previous page displayed.
|
||||
* This is the same as pressing the backbutton on Android device.
|
||||
*/
|
||||
backHistory: function () {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'backHistory', []);
|
||||
},
|
||||
|
||||
/**
|
||||
* Override the default behavior of the Android back button.
|
||||
* If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
|
||||
*
|
||||
* Note: The user should not have to call this method. Instead, when the user
|
||||
* registers for the "backbutton" event, this is automatically done.
|
||||
*
|
||||
* @param override T=override, F=cancel override
|
||||
*/
|
||||
overrideBackbutton: function (override) {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'overrideBackbutton', [override]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Override the default behavior of the Android volume button.
|
||||
* If overridden, when the volume button is pressed, the "volume[up|down]button"
|
||||
* JavaScript event will be fired.
|
||||
*
|
||||
* Note: The user should not have to call this method. Instead, when the user
|
||||
* registers for the "volume[up|down]button" event, this is automatically done.
|
||||
*
|
||||
* @param button volumeup, volumedown
|
||||
* @param override T=override, F=cancel override
|
||||
*/
|
||||
overrideButton: function (button, override) {
|
||||
exec(null, null, APP_PLUGIN_NAME, 'overrideButton', [button, override]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Exit and terminate the application.
|
||||
*/
|
||||
exitApp: function () {
|
||||
return exec(null, null, APP_PLUGIN_NAME, 'exitApp', []);
|
||||
}
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="lib" path="libs/commons-codec-1.6.jar"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Cordova</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -17,52 +17,6 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
|
||||
package="org.apache.cordova" android:versionName="1.1" android:versionCode="5">
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:smallScreens="true"
|
||||
android:resizeable="true"
|
||||
android:anyDensity="true"
|
||||
/>
|
||||
<!-- android:xlargeScreens="true" screen supported only after Android-9 -->
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name"
|
||||
android:debuggable="true">
|
||||
<activity android:name=".StandAlone" android:windowSoftInputMode="adjustPan"
|
||||
android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="org.apache.cordova.DroidGap" android:label="@string/app_name"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<uses-sdk android:minSdkVersion="2" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
|
||||
</manifest>
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked in Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
||||
85
framework/build.gradle
Normal file
@@ -0,0 +1,85 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
buildscript {
|
||||
apply from: 'cordova.gradle'
|
||||
apply from: 'repositories.gradle'
|
||||
|
||||
repositories repos
|
||||
|
||||
dependencies {
|
||||
// Android Gradle Plugin (AGP) Build Tools
|
||||
classpath "com.android.tools.build:gradle:${cordovaConfig.AGP_VERSION}"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply from: 'repositories.gradle'
|
||||
repositories repos
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion cordovaConfig.SDK_VERSION
|
||||
buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
// For the Android Cordova Lib, we allow changing the minSdkVersion, but it is at the users own risk
|
||||
defaultConfig {
|
||||
minSdkVersion cordovaConfig.MIN_SDK_VERSION
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/LICENSE'
|
||||
exclude 'META-INF/LICENSE.txt'
|
||||
exclude 'META-INF/DEPENDENCIES'
|
||||
exclude 'META-INF/NOTICE'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.appcompat:appcompat:${cordovaConfig.ANDROIDX_APP_COMPAT_VERSION}"
|
||||
implementation "androidx.webkit:webkit:${cordovaConfig.ANDROIDX_WEBKIT_VERSION}"
|
||||
}
|
||||
|
||||
/**
|
||||
* In a project created though CLI, the `cordova-publish.gradle` file is not copied to the `framework` dir.
|
||||
* App development (CLI) projects can not and should not publish our framework.
|
||||
* In this case, there is no need for the gradle build process to know about the publish process.
|
||||
*/
|
||||
def cordovaPublishGradle = './cordova-publish.gradle'
|
||||
if(file(cordovaPublishGradle).exists()) {
|
||||
apply from: cordovaPublishGradle
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<project name="Cordova" default="jar">
|
||||
|
||||
<!-- LOAD VERSION -->
|
||||
<loadfile property="version" srcFile="../VERSION">
|
||||
<filterchain>
|
||||
<striplinebreaks/>
|
||||
</filterchain>
|
||||
</loadfile>
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<loadproperties srcFile="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- We need to setup the double quote. -->
|
||||
<property name="dblQuote">"</property>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'"
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!-- version-tag: custom -->
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
/* This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir} */
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
<!-- Combine JavaScript files into one cordova-uncompressed.js file. -->
|
||||
<target name="build-javascript" depends="clean">
|
||||
|
||||
<!-- Clean up existing files -->
|
||||
<!--<delete file="assets/www/cordova_${version}.js"/>-->
|
||||
|
||||
<!-- Create uncompressed JS file -->
|
||||
<concat destfile="assets/www/cordova-${version}.js">
|
||||
<filelist dir="assets/js" files="cordova.android.js"/>
|
||||
</concat>
|
||||
|
||||
<!-- update project files to reference cordova-x.x.x.min.js -->
|
||||
<replaceregexp match="cordova(.*)\.js" replace="cordova-${version}.js" byline="true">
|
||||
<fileset file="assets/www/index.html" />
|
||||
<fileset file="../bin/templates/project/assets/www/index.html" />
|
||||
</replaceregexp>
|
||||
|
||||
<!-- This is sketchy, but it works, ${dblQuote} does not -->
|
||||
<replaceregexp match="cordovaVersion = [\u0022].*[\u0022];" replace='cordovaVersion = ${dblQuote}${version}${dblQuote};' byline="true">
|
||||
<fileset file="src/org/apache/cordova/Device.java" />
|
||||
</replaceregexp>
|
||||
</target>
|
||||
|
||||
<!-- Build Cordova jar file that includes all native code, and Cordova JS file
|
||||
that includes all JavaScript code.
|
||||
-->
|
||||
<target name="jar" depends="build-javascript, -compile">
|
||||
<jar jarfile="cordova-${version}.jar" basedir="bin/classes" excludes="org/apache/cordova/R.class,org/apache/cordova/R$*.class"/>
|
||||
</target>
|
||||
|
||||
<!-- tests for Java files -->
|
||||
<property name="test.dir" location="test/org/apache/cordova" />
|
||||
|
||||
<path id="test.classpath">
|
||||
<!-- requires both junit and cordova -->
|
||||
<pathelement location="libs/junit-4.10.jar" />
|
||||
<pathelement location="cordova-${version}.jar" />
|
||||
<pathelement location="${test.dir}" />
|
||||
</path>
|
||||
|
||||
<target name="compile-test">
|
||||
<javac srcdir="${test.dir}" >
|
||||
<classpath refid="test.classpath" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="test" depends="jar, compile-test">
|
||||
<junit showoutput="true">
|
||||
<classpath refid="test.classpath" />
|
||||
<formatter type="brief" usefile="false" />
|
||||
<batchtest fork="yes">
|
||||
<fileset dir="${test.dir}">
|
||||
<include name="*Test.java" />
|
||||
<include name="**/*Test.java" />
|
||||
</fileset>
|
||||
</batchtest>
|
||||
</junit>
|
||||
</target>
|
||||
|
||||
<target name="cordova_debug" depends="build-javascript, debug">
|
||||
</target>
|
||||
|
||||
<target name="cordova_release" depends="build-javascript, release">
|
||||
</target>
|
||||
|
||||
</project>
|
||||
13
framework/cdv-gradle-config-defaults.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"MIN_SDK_VERSION": 22,
|
||||
"SDK_VERSION": 30,
|
||||
"GRADLE_VERSION": "7.1.1",
|
||||
"BUILD_TOOLS_VERSION": "30.0.3",
|
||||
"AGP_VERSION": "4.2.2",
|
||||
"KOTLIN_VERSION": "1.5.20",
|
||||
"ANDROIDX_APP_COMPAT_VERSION": "1.3.0",
|
||||
"ANDROIDX_WEBKIT_VERSION": "1.4.0",
|
||||
"GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION": "4.3.5",
|
||||
"IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED": false,
|
||||
"IS_GRADLE_PLUGIN_KOTLIN_ENABLED": false
|
||||
}
|
||||
79
framework/cordova-publish.gradle
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
String getCordovaAndroidVersion() {
|
||||
// Fetch Data from Cordova-Android package.json (Used only by framework build/publishing)
|
||||
def cordovaAndroidRepoPackageJson = "$projectDir/../package.json"
|
||||
if(file(cordovaAndroidRepoPackageJson).exists()) {
|
||||
def packageJsonFile = new File(cordovaAndroidRepoPackageJson)
|
||||
def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonFile.text)
|
||||
return packageJson.version
|
||||
}
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
Cordova(MavenPublication) {
|
||||
groupId = 'org.apache.cordova'
|
||||
artifactId = 'framework'
|
||||
version = getCordovaAndroidVersion()
|
||||
|
||||
artifact(sourcesJar)
|
||||
artifact("$buildDir/outputs/aar/framework-release.aar")
|
||||
|
||||
pom {
|
||||
name = 'Cordova'
|
||||
description = 'A library to build Cordova-based projects for the Android platform.'
|
||||
url = 'https://cordova.apache.org'
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = 'Apache License, Version 2.0'
|
||||
url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id = 'stevengill'
|
||||
name = 'Steve Gill'
|
||||
}
|
||||
developer {
|
||||
id = 'erisu'
|
||||
name = 'Bryan Ellis'
|
||||
email = 'erisu@apache.org'
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/apache/cordova-android.git'
|
||||
developerConnection = 'scm:git:git@github.com:apache/cordova-android.git'
|
||||
url = 'https://github.com/apache/cordova-android'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
228
framework/cordova.gradle
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern
|
||||
import io.github.g00fy2.versioncompare.Version
|
||||
|
||||
String doEnsureValueExists(filePath, props, key) {
|
||||
if (props.get(key) == null) {
|
||||
throw new GradleException(filePath + ': Missing key required "' + key + '"')
|
||||
}
|
||||
return props.get(key)
|
||||
}
|
||||
|
||||
String doGetProjectTarget() {
|
||||
def props = new Properties()
|
||||
def propertiesFile = 'project.properties';
|
||||
if(!(file(propertiesFile).exists())) {
|
||||
propertiesFile = '../project.properties';
|
||||
}
|
||||
file(propertiesFile).withReader { reader ->
|
||||
props.load(reader)
|
||||
}
|
||||
return doEnsureValueExists('project.properties', props, 'target')
|
||||
}
|
||||
|
||||
Boolean isVersionValid(version) {
|
||||
return !(new Version(version)).isEqual('0.0.0')
|
||||
}
|
||||
|
||||
String doFindLatestInstalledBuildTools(String minBuildToolsVersionString) {
|
||||
def buildToolsDirContents
|
||||
try {
|
||||
def buildToolsDir = new File(getAndroidSdkDir(), "build-tools")
|
||||
buildToolsDirContents = buildToolsDir.list()
|
||||
} catch (e) {
|
||||
println "An exception occurred while trying to find the Android build tools."
|
||||
throw e
|
||||
}
|
||||
|
||||
def highestBuildToolsVersion = buildToolsDirContents
|
||||
.collect { new Version(it) }
|
||||
// Invalid inputs will be handled as 0.0.0
|
||||
.findAll { it.isHigherThan('0.0.0') }
|
||||
.max()
|
||||
|
||||
if (highestBuildToolsVersion == null) {
|
||||
throw new RuntimeException("""
|
||||
No installed build tools found. Install the Android build tools
|
||||
version ${minBuildToolsVersionString} or higher.
|
||||
""".replaceAll(/\s+/, ' ').trim())
|
||||
}
|
||||
|
||||
if (highestBuildToolsVersion.isLowerThan(minBuildToolsVersionString)) {
|
||||
throw new RuntimeException("""
|
||||
No usable Android build tools found. Highest installed version is
|
||||
${highestBuildToolsVersion.getOriginalString()}; minimum version
|
||||
required is ${minBuildToolsVersionString}.
|
||||
""".replaceAll(/\s+/, ' ').trim())
|
||||
}
|
||||
|
||||
highestBuildToolsVersion.getOriginalString()
|
||||
}
|
||||
|
||||
String getAndroidSdkDir() {
|
||||
def rootDir = project.rootDir
|
||||
def androidSdkDir = null
|
||||
String envVar = System.getenv("ANDROID_SDK_ROOT")
|
||||
if (envVar == null) {
|
||||
envVar = System.getenv("ANDROID_HOME")
|
||||
}
|
||||
|
||||
def localProperties = new File(rootDir, 'local.properties')
|
||||
String systemProperty = System.getProperty("android.home")
|
||||
if (envVar != null) {
|
||||
androidSdkDir = envVar
|
||||
} else if (localProperties.exists()) {
|
||||
Properties properties = new Properties()
|
||||
localProperties.withInputStream { instr ->
|
||||
properties.load(instr)
|
||||
}
|
||||
def sdkDirProp = properties.getProperty('sdk.dir')
|
||||
if (sdkDirProp != null) {
|
||||
androidSdkDir = sdkDirProp
|
||||
} else {
|
||||
sdkDirProp = properties.getProperty('android.dir')
|
||||
if (sdkDirProp != null) {
|
||||
androidSdkDir = (new File(rootDir, sdkDirProp)).getAbsolutePath()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (androidSdkDir == null && systemProperty != null) {
|
||||
androidSdkDir = systemProperty
|
||||
}
|
||||
if (androidSdkDir == null) {
|
||||
throw new RuntimeException(
|
||||
"Unable to determine Android SDK directory.")
|
||||
}
|
||||
androidSdkDir
|
||||
}
|
||||
|
||||
def doExtractIntFromManifest(name) {
|
||||
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
|
||||
def pattern = Pattern.compile(name + "=\"(\\d+)\"")
|
||||
def matcher = pattern.matcher(manifestFile.getText())
|
||||
matcher.find()
|
||||
return new BigInteger(matcher.group(1))
|
||||
}
|
||||
|
||||
def doExtractStringFromManifest(name) {
|
||||
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
|
||||
def pattern = Pattern.compile(name + "=\"(\\S+)\"")
|
||||
def matcher = pattern.matcher(manifestFile.getText())
|
||||
matcher.find()
|
||||
return matcher.group(1)
|
||||
}
|
||||
|
||||
def doGetConfigXml() {
|
||||
def xml = file("src/main/res/xml/config.xml").getText()
|
||||
// Disable namespace awareness since Cordova doesn't use them properly
|
||||
return new XmlParser(false, false).parseText(xml)
|
||||
}
|
||||
|
||||
def doGetConfigPreference(name, defaultValue) {
|
||||
name = name.toLowerCase()
|
||||
def root = doGetConfigXml()
|
||||
|
||||
def ret = defaultValue
|
||||
root.preference.each { it ->
|
||||
def attrName = it.attribute("name")
|
||||
if (attrName && attrName.toLowerCase() == name) {
|
||||
ret = it.attribute("value")
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
def doApplyCordovaConfigCustomization() {
|
||||
// Apply user overide properties that comes from the "--gradleArg=-P" parameters
|
||||
if (project.hasProperty('cdvMinSdkVersion')) {
|
||||
cordovaConfig.MIN_SDK_VERSION = Integer.parseInt('' + cdvMinSdkVersion)
|
||||
}
|
||||
if (project.hasProperty('cdvSdkVersion')) {
|
||||
cordovaConfig.SDK_VERSION = Integer.parseInt('' + cdvSdkVersion)
|
||||
}
|
||||
if (project.hasProperty('cdvMaxSdkVersion')) {
|
||||
cordovaConfig.MAX_SDK_VERSION = Integer.parseInt('' + cdvMaxSdkVersion)
|
||||
}
|
||||
if (project.hasProperty('cdvBuildToolsVersion')) {
|
||||
cordovaConfig.BUILD_TOOLS_VERSION = cdvBuildToolsVersion
|
||||
}
|
||||
if (project.hasProperty('cdvAndroidXAppCompatVersion')) {
|
||||
cordovaConfig.ANDROIDX_APP_COMPAT_VERSION = cdvAndroidXAppCompatVersion
|
||||
}
|
||||
if (project.hasProperty('cdvAndroidXWebKitVersion')) {
|
||||
cordovaConfig.ANDROIDX_WEBKIT_VERSION = cdvAndroidXWebKitVersion
|
||||
}
|
||||
|
||||
// Ensure the latest installed build tools is selected, with or without defined override
|
||||
cordovaConfig.LATEST_INSTALLED_BUILD_TOOLS = doFindLatestInstalledBuildTools(
|
||||
cordovaConfig.BUILD_TOOLS_VERSION
|
||||
)
|
||||
}
|
||||
|
||||
// Properties exported here are visible to all plugins.
|
||||
ext {
|
||||
def defaultsFilePath = './cdv-gradle-config-defaults.json'
|
||||
def projectConfigFilePath = "$rootDir/cdv-gradle-config.json"
|
||||
def targetConfigFilePath = null
|
||||
|
||||
/**
|
||||
* Check if the project config file path exists. This file will exist if coming from CLI project.
|
||||
* If this file does not exist, falls back onto the default file.
|
||||
* This scenario can occur if building the framework's AAR package for publishing.
|
||||
*/
|
||||
if(file(projectConfigFilePath).exists()) {
|
||||
targetConfigFilePath = projectConfigFilePath
|
||||
} else {
|
||||
targetConfigFilePath = defaultsFilePath
|
||||
}
|
||||
|
||||
def jsonFile = new File(targetConfigFilePath)
|
||||
cordovaConfig = new groovy.json.JsonSlurper().parseText(jsonFile.text)
|
||||
|
||||
// Apply Gradle Properties
|
||||
doApplyCordovaConfigCustomization()
|
||||
|
||||
// These helpers are shared, but are not guaranteed to be stable / unchanged.
|
||||
privateHelpers = {}
|
||||
privateHelpers.getProjectTarget = { doGetProjectTarget() }
|
||||
privateHelpers.applyCordovaConfigCustomization = { doApplyCordovaConfigCustomization() }
|
||||
privateHelpers.extractIntFromManifest = { name -> doExtractIntFromManifest(name) }
|
||||
privateHelpers.extractStringFromManifest = { name -> doExtractStringFromManifest(name) }
|
||||
privateHelpers.ensureValueExists = { filePath, props, key -> doEnsureValueExists(filePath, props, key) }
|
||||
|
||||
// These helpers can be used by plugins / projects and will not change.
|
||||
cdvHelpers = {}
|
||||
// Returns a XmlParser for the config.xml. Added in 4.1.0.
|
||||
cdvHelpers.getConfigXml = { doGetConfigXml() }
|
||||
// Returns the value for the desired <preference>. Added in 4.1.0.
|
||||
cdvHelpers.getConfigPreference = { name, defaultValue -> doGetConfigPreference(name, defaultValue) }
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'io.github.g00fy2:versioncompare:1.4.1@jar'
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
# Project target.
|
||||
target=android-14
|
||||
apk-configurations=
|
||||
19
framework/gradle.properties
Normal file
@@ -0,0 +1,19 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
5
framework/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#Thu Nov 09 10:50:25 PST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -1,14 +1,12 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
# GENERATED FILE! DO NOT EDIT!
|
||||
|
||||
# This file was originally created by the Android Tools, but is now
|
||||
# used by cordova-android to manage the project configuration.
|
||||
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
|
||||
# Project target.
|
||||
target=Google Inc.:Google APIs:15
|
||||
apk-configurations=
|
||||
renderscript.opt.level=O0
|
||||
android.library=true
|
||||
|
||||
22
framework/repositories.gradle
Normal file
@@ -0,0 +1,22 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
ext.repos = {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 92 KiB |
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<WebView android:id="@+id/appView"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="fill_parent"
|
||||
/>
|
||||
</LinearLayout>
|
||||
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<cordova>
|
||||
<!--
|
||||
access elements control the Android whitelist.
|
||||
Domains are assumed blocked unless set otherwise
|
||||
-->
|
||||
|
||||
<access origin="http://127.0.0.1*"/> <!-- allow local pages -->
|
||||
|
||||
<!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
|
||||
<!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
|
||||
<!-- <access origin=".*"/> Allow all domains, suggested development use only -->
|
||||
|
||||
<log level="DEBUG"/>
|
||||
<preference name="useBrowserHistory" value="false" />
|
||||
</cordova>
|
||||
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<plugins>
|
||||
<plugin name="App" value="org.apache.cordova.App"/>
|
||||
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
|
||||
<plugin name="Device" value="org.apache.cordova.Device"/>
|
||||
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
|
||||
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
|
||||
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
|
||||
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
|
||||
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
|
||||
<plugin name="File" value="org.apache.cordova.FileUtils"/>
|
||||
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
|
||||
<plugin name="Notification" value="org.apache.cordova.Notification"/>
|
||||
<plugin name="Storage" value="org.apache.cordova.Storage"/>
|
||||
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
|
||||
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
|
||||
<plugin name="Capture" value="org.apache.cordova.Capture"/>
|
||||
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
|
||||
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
|
||||
</plugins>
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package com.phonegap.api;
|
||||
|
||||
/**
|
||||
* Log to Android logging system.
|
||||
*
|
||||
* Log message can be a string or a printf formatted string with arguments.
|
||||
* See http://developer.android.com/reference/java/util/Formatter.html
|
||||
*/
|
||||
public class LOG extends org.apache.cordova.api.LOG {
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package com.phonegap.api;
|
||||
|
||||
/**
|
||||
* Plugin interface must be implemented by any plugin classes.
|
||||
*
|
||||
* The execute method is called by the PluginManager.
|
||||
*/
|
||||
public abstract class Plugin extends org.apache.cordova.api.Plugin {
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package com.phonegap.api;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class PluginResult extends org.apache.cordova.api.PluginResult {
|
||||
|
||||
public PluginResult(Status status) {
|
||||
super(status);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, String message) {
|
||||
super(status, message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONArray message) {
|
||||
super(status, message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONObject message) {
|
||||
super(status, message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, int i) {
|
||||
super(status, i);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, float f) {
|
||||
super(status, f);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, boolean b) {
|
||||
super(status, b);
|
||||
}
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.cordova.api.CordovaInterface;
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* This class listens to the accelerometer sensor and stores the latest
|
||||
* acceleration values x,y,z.
|
||||
*/
|
||||
public class AccelListener extends Plugin implements SensorEventListener {
|
||||
|
||||
public static int STOPPED = 0;
|
||||
public static int STARTING = 1;
|
||||
public static int RUNNING = 2;
|
||||
public static int ERROR_FAILED_TO_START = 3;
|
||||
|
||||
private float x,y,z; // most recent acceleration values
|
||||
private long timestamp; // time of most recent value
|
||||
private int status; // status of listener
|
||||
private int accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
|
||||
|
||||
private SensorManager sensorManager; // Sensor manager
|
||||
private Sensor mSensor; // Acceleration sensor returned by sensor manager
|
||||
|
||||
private String callbackId; // Keeps track of the single "start" callback ID passed in from JS
|
||||
|
||||
/**
|
||||
* Create an accelerometer listener.
|
||||
*/
|
||||
public AccelListener() {
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.z = 0;
|
||||
this.timestamp = 0;
|
||||
this.setStatus(AccelListener.STOPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context of the Command. This can then be used to do things like
|
||||
* get file paths associated with the Activity.
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
|
||||
public void setContext(CordovaInterface ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.NO_RESULT;
|
||||
String message = "";
|
||||
PluginResult result = new PluginResult(status, message);
|
||||
result.setKeepCallback(true);
|
||||
|
||||
if (action.equals("start")) {
|
||||
this.callbackId = callbackId;
|
||||
if (this.status != AccelListener.RUNNING) {
|
||||
// If not running, then this is an async call, so don't worry about waiting
|
||||
// We drop the callback onto our stack, call start, and let start and the sensor callback fire off the callback down the road
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
else if (action.equals("stop")) {
|
||||
if (this.status == AccelListener.RUNNING) {
|
||||
this.stop();
|
||||
}
|
||||
} else {
|
||||
// Unsupported action
|
||||
return new PluginResult(PluginResult.Status.INVALID_ACTION);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by AccelBroker when listener is to be shut down.
|
||||
* Stop listener.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/**
|
||||
* Start listening for acceleration sensor.
|
||||
*
|
||||
* @return status of listener
|
||||
*/
|
||||
private int start() {
|
||||
// If already starting or running, then just return
|
||||
if ((this.status == AccelListener.RUNNING) || (this.status == AccelListener.STARTING)) {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
this.setStatus(AccelListener.STARTING);
|
||||
|
||||
// Get accelerometer from sensor manager
|
||||
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
|
||||
|
||||
// If found, then register as listener
|
||||
if ((list != null) && (list.size() > 0)) {
|
||||
this.mSensor = list.get(0);
|
||||
this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_UI);
|
||||
this.setStatus(AccelListener.STARTING);
|
||||
} else {
|
||||
this.setStatus(AccelListener.ERROR_FAILED_TO_START);
|
||||
this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to.");
|
||||
return this.status;
|
||||
}
|
||||
|
||||
// Wait until running
|
||||
long timeout = 2000;
|
||||
while ((this.status == STARTING) && (timeout > 0)) {
|
||||
timeout = timeout - 100;
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (timeout == 0) {
|
||||
this.setStatus(AccelListener.ERROR_FAILED_TO_START);
|
||||
this.fail(AccelListener.ERROR_FAILED_TO_START, "Accelerometer could not be started.");
|
||||
}
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop listening to acceleration sensor.
|
||||
*/
|
||||
private void stop() {
|
||||
if (this.status != AccelListener.STOPPED) {
|
||||
this.sensorManager.unregisterListener(this);
|
||||
}
|
||||
this.setStatus(AccelListener.STOPPED);
|
||||
this.accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the accuracy of the sensor has changed.
|
||||
*
|
||||
* @param sensor
|
||||
* @param accuracy
|
||||
*/
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
// Only look at accelerometer events
|
||||
if (sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If not running, then just return
|
||||
if (this.status == AccelListener.STOPPED) {
|
||||
return;
|
||||
}
|
||||
this.accuracy = accuracy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sensor listener event.
|
||||
*
|
||||
* @param SensorEvent event
|
||||
*/
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
// Only look at accelerometer events
|
||||
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If not running, then just return
|
||||
if (this.status == AccelListener.STOPPED) {
|
||||
return;
|
||||
}
|
||||
this.setStatus(AccelListener.RUNNING);
|
||||
|
||||
if (this.accuracy >= SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
|
||||
|
||||
// Save time that event was received
|
||||
this.timestamp = System.nanoTime();
|
||||
this.x = event.values[0];
|
||||
this.y = event.values[1];
|
||||
this.z = event.values[2];
|
||||
|
||||
this.win();
|
||||
}
|
||||
}
|
||||
|
||||
// Sends an error back to JS
|
||||
private void fail(int code, String message) {
|
||||
// Error object
|
||||
JSONObject errorObj = new JSONObject();
|
||||
try {
|
||||
errorObj.put("code", code);
|
||||
errorObj.put("message", message);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
PluginResult err = new PluginResult(PluginResult.Status.ERROR, errorObj);
|
||||
err.setKeepCallback(true);
|
||||
|
||||
this.error(err, this.callbackId);
|
||||
}
|
||||
|
||||
private void win() {
|
||||
// Success return object
|
||||
PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON());
|
||||
result.setKeepCallback(true);
|
||||
|
||||
this.success(result, this.callbackId);
|
||||
}
|
||||
|
||||
private void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
private JSONObject getAccelerationJSON() {
|
||||
JSONObject r = new JSONObject();
|
||||
try {
|
||||
r.put("x", this.x);
|
||||
r.put("y", this.y);
|
||||
r.put("z", this.z);
|
||||
r.put("timestamp", this.timestamp);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
170
framework/src/org/apache/cordova/AllowList.java
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.cordova.LOG;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
public class AllowList {
|
||||
private static class URLPattern {
|
||||
public Pattern scheme;
|
||||
public Pattern host;
|
||||
public Integer port;
|
||||
public Pattern path;
|
||||
|
||||
private String regexFromPattern(String pattern, boolean allowWildcards) {
|
||||
final String toReplace = "\\.[]{}()^$?+|";
|
||||
StringBuilder regex = new StringBuilder();
|
||||
for (int i=0; i < pattern.length(); i++) {
|
||||
char c = pattern.charAt(i);
|
||||
if (c == '*' && allowWildcards) {
|
||||
regex.append(".");
|
||||
} else if (toReplace.indexOf(c) > -1) {
|
||||
regex.append('\\');
|
||||
}
|
||||
regex.append(c);
|
||||
}
|
||||
return regex.toString();
|
||||
}
|
||||
|
||||
public URLPattern(String scheme, String host, String port, String path) throws MalformedURLException {
|
||||
try {
|
||||
if (scheme == null || "*".equals(scheme)) {
|
||||
this.scheme = null;
|
||||
} else {
|
||||
this.scheme = Pattern.compile(regexFromPattern(scheme, false), Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
if ("*".equals(host)) {
|
||||
this.host = null;
|
||||
} else if (host.startsWith("*.")) {
|
||||
this.host = Pattern.compile("([a-z0-9.-]*\\.)?" + regexFromPattern(host.substring(2), false), Pattern.CASE_INSENSITIVE);
|
||||
} else {
|
||||
this.host = Pattern.compile(regexFromPattern(host, false), Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
if (port == null || "*".equals(port)) {
|
||||
this.port = null;
|
||||
} else {
|
||||
this.port = Integer.parseInt(port,10);
|
||||
}
|
||||
if (path == null || "/*".equals(path)) {
|
||||
this.path = null;
|
||||
} else {
|
||||
this.path = Pattern.compile(regexFromPattern(path, true));
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new MalformedURLException("Port must be a number");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(Uri uri) {
|
||||
try {
|
||||
return ((scheme == null || scheme.matcher(uri.getScheme()).matches()) &&
|
||||
(host == null || host.matcher(uri.getHost()).matches()) &&
|
||||
(port == null || port.equals(uri.getPort())) &&
|
||||
(path == null || path.matcher(uri.getPath()).matches()));
|
||||
} catch (Exception e) {
|
||||
LOG.d(TAG, e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<URLPattern> allowList;
|
||||
|
||||
public static final String TAG = "CordovaAllowList";
|
||||
|
||||
public AllowList() {
|
||||
this.allowList = new ArrayList<URLPattern>();
|
||||
}
|
||||
|
||||
/* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
|
||||
*
|
||||
* <url-pattern> := <scheme>://<host><path>
|
||||
* <scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'chrome-extension'
|
||||
* <host> := '*' | '*.' <any char except '/' and '*'>+
|
||||
* <path> := '/' <any chars>
|
||||
*
|
||||
* We extend this to explicitly allow a port attached to the host, and we allow
|
||||
* the scheme to be omitted for backwards compatibility. (Also host is not required
|
||||
* to begin with a "*" or "*.".)
|
||||
*/
|
||||
public void addAllowListEntry(String origin, boolean subdomains) {
|
||||
if (allowList != null) {
|
||||
try {
|
||||
// Unlimited access to network resources
|
||||
if (origin.compareTo("*") == 0) {
|
||||
LOG.d(TAG, "Unlimited access to network resources");
|
||||
allowList = null;
|
||||
}
|
||||
else { // specific access
|
||||
Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
|
||||
Matcher m = parts.matcher(origin);
|
||||
if (m.matches()) {
|
||||
String scheme = m.group(2);
|
||||
String host = m.group(4);
|
||||
// Special case for two urls which are allowed to have empty hosts
|
||||
if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*";
|
||||
String port = m.group(8);
|
||||
String path = m.group(9);
|
||||
if (scheme == null) {
|
||||
// XXX making it stupid friendly for people who forget to include protocol/SSL
|
||||
allowList.add(new URLPattern("http", host, port, path));
|
||||
allowList.add(new URLPattern("https", host, port, path));
|
||||
} else {
|
||||
allowList.add(new URLPattern(scheme, host, port, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.d(TAG, "Failed to add origin %s", origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if URL is in approved list of URLs to load.
|
||||
*
|
||||
* @param uri
|
||||
* @return true if wide open or allow listed
|
||||
*/
|
||||
public boolean isUrlAllowListed(String uri) {
|
||||
// If there is no allowList, then it's wide open
|
||||
if (allowList == null) return true;
|
||||
|
||||
Uri parsedUri = Uri.parse(uri);
|
||||
// Look for match in allow list
|
||||
Iterator<URLPattern> pit = allowList.iterator();
|
||||
while (pit.hasNext()) {
|
||||
URLPattern p = pit.next();
|
||||
if (p.matches(parsedUri)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
165
framework/src/org/apache/cordova/AllowListPlugin.java
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.CordovaPlugin;
|
||||
import org.apache.cordova.ConfigXmlParser;
|
||||
import org.apache.cordova.LOG;
|
||||
import org.apache.cordova.AllowList;
|
||||
import org.apache.cordova.CordovaPreferences;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public class AllowListPlugin extends CordovaPlugin {
|
||||
public static final String PLUGIN_NAME = "CordovaAllowListPlugin";
|
||||
protected static final String LOG_TAG = "CordovaAllowListPlugin";
|
||||
|
||||
private AllowList allowedNavigations;
|
||||
private AllowList allowedIntents;
|
||||
private AllowList allowedRequests;
|
||||
|
||||
// Used when instantiated via reflection by PluginManager
|
||||
public AllowListPlugin() { }
|
||||
|
||||
// These can be used by embedders to allow Java-configuration of an allow list.
|
||||
public AllowListPlugin(Context context) {
|
||||
this(new AllowList(), new AllowList(), null);
|
||||
new CustomConfigXmlParser().parse(context);
|
||||
}
|
||||
|
||||
public AllowListPlugin(XmlPullParser xmlParser) {
|
||||
this(new AllowList(), new AllowList(), null);
|
||||
new CustomConfigXmlParser().parse(xmlParser);
|
||||
}
|
||||
|
||||
public AllowListPlugin(AllowList allowedNavigations, AllowList allowedIntents, AllowList allowedRequests) {
|
||||
if (allowedRequests == null) {
|
||||
allowedRequests = new AllowList();
|
||||
allowedRequests.addAllowListEntry("file:///*", false);
|
||||
allowedRequests.addAllowListEntry("data:*", false);
|
||||
}
|
||||
|
||||
this.allowedNavigations = allowedNavigations;
|
||||
this.allowedIntents = allowedIntents;
|
||||
this.allowedRequests = allowedRequests;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pluginInitialize() {
|
||||
if (this.allowedNavigations == null) {
|
||||
this.allowedNavigations = new AllowList();
|
||||
this.allowedIntents = new AllowList();
|
||||
this.allowedRequests = new AllowList();
|
||||
|
||||
new CustomConfigXmlParser().parse(webView.getContext());
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomConfigXmlParser extends ConfigXmlParser {
|
||||
private CordovaPreferences prefs = new CordovaPreferences();
|
||||
|
||||
@Override
|
||||
public void handleStartTag(XmlPullParser xml) {
|
||||
String strNode = xml.getName();
|
||||
if (strNode.equals("content")) {
|
||||
String startPage = xml.getAttributeValue(null, "src");
|
||||
allowedNavigations.addAllowListEntry(startPage, false);
|
||||
|
||||
// Allow origin for WebViewAssetLoader
|
||||
if (!this.prefs.getBoolean("AndroidInsecureFileModeEnabled", false)) {
|
||||
allowedNavigations.addAllowListEntry("https://" + this.prefs.getString("hostname", "localhost"), false);
|
||||
}
|
||||
} else if (strNode.equals("allow-navigation")) {
|
||||
String origin = xml.getAttributeValue(null, "href");
|
||||
if ("*".equals(origin)) {
|
||||
allowedNavigations.addAllowListEntry("http://*/*", false);
|
||||
allowedNavigations.addAllowListEntry("https://*/*", false);
|
||||
allowedNavigations.addAllowListEntry("data:*", false);
|
||||
} else {
|
||||
allowedNavigations.addAllowListEntry(origin, false);
|
||||
}
|
||||
} else if (strNode.equals("allow-intent")) {
|
||||
String origin = xml.getAttributeValue(null, "href");
|
||||
allowedIntents.addAllowListEntry(origin, false);
|
||||
} else if (strNode.equals("access")) {
|
||||
String origin = xml.getAttributeValue(null, "origin");
|
||||
|
||||
if (origin != null) {
|
||||
if ("*".equals(origin)) {
|
||||
allowedRequests.addAllowListEntry("http://*/*", false);
|
||||
allowedRequests.addAllowListEntry("https://*/*", false);
|
||||
} else {
|
||||
String subdomains = xml.getAttributeValue(null, "subdomains");
|
||||
allowedRequests.addAllowListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEndTag(XmlPullParser xml) { }
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean shouldAllowNavigation(String url) {
|
||||
return this.allowedNavigations.isUrlAllowListed(url)
|
||||
? true
|
||||
: null; // default policy
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean shouldAllowRequest(String url) {
|
||||
return (this.shouldAllowNavigation(url) || this.allowedRequests.isUrlAllowListed(url))
|
||||
? true
|
||||
: null; // default policy
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean shouldOpenExternalUrl(String url) {
|
||||
return (this.allowedIntents.isUrlAllowListed(url))
|
||||
? true
|
||||
: null; // default policy
|
||||
}
|
||||
|
||||
public AllowList getAllowedNavigations() {
|
||||
return this.allowedNavigations;
|
||||
}
|
||||
|
||||
public void setAllowedNavigations(AllowList allowedNavigations) {
|
||||
this.allowedNavigations = allowedNavigations;
|
||||
}
|
||||
|
||||
public AllowList getAllowedIntents() {
|
||||
return this.allowedIntents;
|
||||
}
|
||||
|
||||
public void setAllowedIntents(AllowList allowedIntents) {
|
||||
this.allowedIntents = allowedIntents;
|
||||
}
|
||||
|
||||
public AllowList getAllowedRequests() {
|
||||
return this.allowedRequests;
|
||||
}
|
||||
|
||||
public void setAllowedRequests(AllowList allowedRequests) {
|
||||
this.allowedRequests = allowedRequests;
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.api.LOG;
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class exposes methods in DroidGap that can be called from JavaScript.
|
||||
*/
|
||||
public class App extends Plugin {
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
if (action.equals("clearCache")) {
|
||||
this.clearCache();
|
||||
}
|
||||
else if (action.equals("show")) { // TODO @bc - Not in master branch. When should this be called?
|
||||
ctx.getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
webView.postMessage("spinner", "stop");
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (action.equals("loadUrl")) {
|
||||
this.loadUrl(args.getString(0), args.optJSONObject(1));
|
||||
}
|
||||
else if (action.equals("cancelLoadUrl")) {
|
||||
this.cancelLoadUrl();
|
||||
}
|
||||
else if (action.equals("clearHistory")) {
|
||||
this.clearHistory();
|
||||
}
|
||||
else if (action.equals("backHistory")) {
|
||||
this.backHistory();
|
||||
}
|
||||
else if (action.equals("overrideButton")) {
|
||||
this.overrideButton(args.getString(0), args.getBoolean(1));
|
||||
}
|
||||
else if (action.equals("overrideBackbutton")) {
|
||||
this.overrideBackbutton(args.getBoolean(0));
|
||||
}
|
||||
else if (action.equals("isBackbuttonOverridden")) {
|
||||
boolean b = this.isBackbuttonOverridden();
|
||||
return new PluginResult(status, b);
|
||||
}
|
||||
else if (action.equals("exitApp")) {
|
||||
this.exitApp();
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clear the resource cache.
|
||||
*/
|
||||
public void clearCache() {
|
||||
this.webView.clearCache(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url
|
||||
* @param props Properties that can be passed in to the DroidGap activity (i.e. loadingDialog, wait, ...)
|
||||
* @throws JSONException
|
||||
*/
|
||||
public void loadUrl(String url, JSONObject props) throws JSONException {
|
||||
LOG.d("App", "App.loadUrl("+url+","+props+")");
|
||||
int wait = 0;
|
||||
boolean openExternal = false;
|
||||
boolean clearHistory = false;
|
||||
|
||||
// If there are properties, then set them on the Activity
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
if (props != null) {
|
||||
JSONArray keys = props.names();
|
||||
for (int i = 0; i < keys.length(); i++) {
|
||||
String key = keys.getString(i);
|
||||
if (key.equals("wait")) {
|
||||
wait = props.getInt(key);
|
||||
}
|
||||
else if (key.equalsIgnoreCase("openexternal")) {
|
||||
openExternal = props.getBoolean(key);
|
||||
}
|
||||
else if (key.equalsIgnoreCase("clearhistory")) {
|
||||
clearHistory = props.getBoolean(key);
|
||||
}
|
||||
else {
|
||||
Object value = props.get(key);
|
||||
if (value == null) {
|
||||
|
||||
}
|
||||
else if (value.getClass().equals(String.class)) {
|
||||
params.put(key, (String)value);
|
||||
}
|
||||
else if (value.getClass().equals(Boolean.class)) {
|
||||
params.put(key, (Boolean)value);
|
||||
}
|
||||
else if (value.getClass().equals(Integer.class)) {
|
||||
params.put(key, (Integer)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If wait property, then delay loading
|
||||
|
||||
if (wait > 0) {
|
||||
try {
|
||||
synchronized(this) {
|
||||
this.wait(wait);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.webView.showWebPage(url, openExternal, clearHistory, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class)
|
||||
*/
|
||||
@Deprecated
|
||||
public void cancelLoadUrl() {
|
||||
this.ctx.cancelLoadUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear page history for the app.
|
||||
*/
|
||||
public void clearHistory() {
|
||||
this.webView.clearHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to previous page displayed.
|
||||
* This is the same as pressing the backbutton on Android device.
|
||||
*/
|
||||
public void backHistory() {
|
||||
this.webView.backHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default behavior of the Android back button.
|
||||
* If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
|
||||
*
|
||||
* @param override T=override, F=cancel override
|
||||
*/
|
||||
public void overrideBackbutton(boolean override) {
|
||||
LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!");
|
||||
webView.bindButton(override);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default behavior of the Android volume buttons.
|
||||
* If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired.
|
||||
*
|
||||
* @param button volumeup, volumedown
|
||||
* @param override T=override, F=cancel override
|
||||
*/
|
||||
public void overrideButton(String button, boolean override) {
|
||||
LOG.i("DroidGap", "WARNING: Volume Button Default Behaviour will be overridden. The volume event will be fired!");
|
||||
webView.bindButton(button, override);
|
||||
}
|
||||
/**
|
||||
* Return whether the Android back button is overridden by the user.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isBackbuttonOverridden() {
|
||||
return this.ctx.isBackButtonBound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the Android application.
|
||||
*/
|
||||
public void exitApp() {
|
||||
this.webView.postMessage("exit", null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,353 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This class called by CordovaActivity to play and record audio.
|
||||
* The file can be local or over a network using http.
|
||||
*
|
||||
* Audio formats supported (tested):
|
||||
* .mp3, .wav
|
||||
*
|
||||
* Local audio files must reside in one of two places:
|
||||
* android_asset: file name must start with /android_asset/sound.mp3
|
||||
* sdcard: file name is just sound.mp3
|
||||
*/
|
||||
public class AudioHandler extends Plugin {
|
||||
|
||||
public static String TAG = "AudioHandler";
|
||||
HashMap<String, AudioPlayer> players; // Audio player object
|
||||
ArrayList<AudioPlayer> pausedForPhone; // Audio players that were paused when phone call came in
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public AudioHandler() {
|
||||
this.players = new HashMap<String, AudioPlayer>();
|
||||
this.pausedForPhone = new ArrayList<AudioPlayer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
if (action.equals("startRecordingAudio")) {
|
||||
this.startRecordingAudio(args.getString(0), args.getString(1));
|
||||
}
|
||||
else if (action.equals("stopRecordingAudio")) {
|
||||
this.stopRecordingAudio(args.getString(0));
|
||||
}
|
||||
else if (action.equals("startPlayingAudio")) {
|
||||
this.startPlayingAudio(args.getString(0), args.getString(1));
|
||||
}
|
||||
else if (action.equals("seekToAudio")) {
|
||||
this.seekToAudio(args.getString(0), args.getInt(1));
|
||||
}
|
||||
else if (action.equals("pausePlayingAudio")) {
|
||||
this.pausePlayingAudio(args.getString(0));
|
||||
}
|
||||
else if (action.equals("stopPlayingAudio")) {
|
||||
this.stopPlayingAudio(args.getString(0));
|
||||
} else if (action.equals("setVolume")) {
|
||||
try {
|
||||
this.setVolume(args.getString(0), Float.parseFloat(args.getString(1)));
|
||||
} catch (NumberFormatException nfe) {
|
||||
//no-op
|
||||
}
|
||||
} else if (action.equals("getCurrentPositionAudio")) {
|
||||
float f = this.getCurrentPositionAudio(args.getString(0));
|
||||
return new PluginResult(status, f);
|
||||
}
|
||||
else if (action.equals("getDurationAudio")) {
|
||||
float f = this.getDurationAudio(args.getString(0), args.getString(1));
|
||||
return new PluginResult(status, f);
|
||||
}
|
||||
else if (action.equals("release")) {
|
||||
boolean b = this.release(args.getString(0));
|
||||
return new PluginResult(status, b);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies if action to be executed returns a value and should be run synchronously.
|
||||
* @param action The action to execute
|
||||
* @return T=returns value
|
||||
*/
|
||||
public boolean isSynch(String action) {
|
||||
if (action.equals("getCurrentPositionAudio")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("getDurationAudio")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all audio players and recorders.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
for (AudioPlayer audio : this.players.values()) {
|
||||
audio.destroy();
|
||||
}
|
||||
this.players.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message is sent to plugin.
|
||||
*
|
||||
* @param id The message id
|
||||
* @param data The message data
|
||||
* @return Object to stop propagation or null
|
||||
*/
|
||||
public Object onMessage(String id, Object data) {
|
||||
|
||||
// If phone message
|
||||
if (id.equals("telephone")) {
|
||||
|
||||
// If phone ringing, then pause playing
|
||||
if ("ringing".equals(data) || "offhook".equals(data)) {
|
||||
|
||||
// Get all audio players and pause them
|
||||
for (AudioPlayer audio : this.players.values()) {
|
||||
if (audio.getState() == AudioPlayer.MEDIA_RUNNING) {
|
||||
this.pausedForPhone.add(audio);
|
||||
audio.pausePlaying();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If phone idle, then resume playing those players we paused
|
||||
else if ("idle".equals(data)) {
|
||||
for (AudioPlayer audio : this.pausedForPhone) {
|
||||
audio.startPlaying(null);
|
||||
}
|
||||
this.pausedForPhone.clear();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Release the audio player instance to save memory.
|
||||
* @param id The id of the audio player
|
||||
*/
|
||||
private boolean release(String id) {
|
||||
if (!this.players.containsKey(id)) {
|
||||
return false;
|
||||
}
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
this.players.remove(id);
|
||||
audio.destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recording and save the specified file.
|
||||
* @param id The id of the audio player
|
||||
* @param file The name of the file
|
||||
*/
|
||||
public void startRecordingAudio(String id, String file) {
|
||||
// If already recording, then just return;
|
||||
if (this.players.containsKey(id)) {
|
||||
return;
|
||||
}
|
||||
AudioPlayer audio = new AudioPlayer(this, id);
|
||||
this.players.put(id, audio);
|
||||
audio.startRecording(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording and save to the file specified when recording started.
|
||||
* @param id The id of the audio player
|
||||
*/
|
||||
public void stopRecordingAudio(String id) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
audio.stopRecording();
|
||||
this.players.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start or resume playing audio file.
|
||||
* @param id The id of the audio player
|
||||
* @param file The name of the audio file.
|
||||
*/
|
||||
public void startPlayingAudio(String id, String file) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio == null) {
|
||||
audio = new AudioPlayer(this, id);
|
||||
this.players.put(id, audio);
|
||||
}
|
||||
audio.startPlaying(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to a location.
|
||||
* @param id The id of the audio player
|
||||
* @param miliseconds int: number of milliseconds to skip 1000 = 1 second
|
||||
*/
|
||||
public void seekToAudio(String id, int milliseconds) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
audio.seekToPlaying(milliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause playing.
|
||||
* @param id The id of the audio player
|
||||
*/
|
||||
public void pausePlayingAudio(String id) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
audio.pausePlaying();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop playing the audio file.
|
||||
* @param id The id of the audio player
|
||||
*/
|
||||
public void stopPlayingAudio(String id) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
audio.stopPlaying();
|
||||
//audio.destroy();
|
||||
//this.players.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current position of playback.
|
||||
* @param id The id of the audio player
|
||||
* @return position in msec
|
||||
*/
|
||||
public float getCurrentPositionAudio(String id) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
return (audio.getCurrentPosition() / 1000.0f);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the audio file.
|
||||
* @param id The id of the audio player
|
||||
* @param file The name of the audio file.
|
||||
* @return The duration in msec.
|
||||
*/
|
||||
public float getDurationAudio(String id, String file) {
|
||||
|
||||
// Get audio file
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
return (audio.getDuration(file));
|
||||
}
|
||||
|
||||
// If not already open, then open the file
|
||||
else {
|
||||
audio = new AudioPlayer(this, id);
|
||||
this.players.put(id, audio);
|
||||
return (audio.getDuration(file));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the audio device to be used for playback.
|
||||
*
|
||||
* @param output 1=earpiece, 2=speaker
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setAudioOutputDevice(int output) {
|
||||
AudioManager audiMgr = (AudioManager) this.ctx.getActivity().getSystemService(Context.AUDIO_SERVICE);
|
||||
if (output == 2) {
|
||||
audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
|
||||
}
|
||||
else if (output == 1) {
|
||||
audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
|
||||
}
|
||||
else {
|
||||
System.out.println("AudioHandler.setAudioOutputDevice() Error: Unknown output device.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio device to be used for playback.
|
||||
*
|
||||
* @return 1=earpiece, 2=speaker
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public int getAudioOutputDevice() {
|
||||
AudioManager audiMgr = (AudioManager) this.ctx.getActivity().getSystemService(Context.AUDIO_SERVICE);
|
||||
if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) {
|
||||
return 1;
|
||||
}
|
||||
else if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_SPEAKER) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the volume for an audio device
|
||||
*
|
||||
* @param id The id of the audio player
|
||||
* @param volume Volume to adjust to 0.0f - 1.0f
|
||||
*/
|
||||
public void setVolume(String id, float volume) {
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
if (audio != null) {
|
||||
audio.setVolume(volume);
|
||||
} else {
|
||||
System.out.println("AudioHandler.setVolume() Error: Unknown Audio Player " + id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,464 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.MediaPlayer.OnCompletionListener;
|
||||
import android.media.MediaPlayer.OnErrorListener;
|
||||
import android.media.MediaPlayer.OnPreparedListener;
|
||||
import android.media.MediaRecorder;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class implements the audio playback and recording capabilities used by Cordova.
|
||||
* It is called by the AudioHandler Cordova class.
|
||||
* Only one file can be played or recorded per class instance.
|
||||
*
|
||||
* Local audio files must reside in one of two places:
|
||||
* android_asset: file name must start with /android_asset/sound.mp3
|
||||
* sdcard: file name is just sound.mp3
|
||||
*/
|
||||
public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener {
|
||||
|
||||
private static final String LOG_TAG = "AudioPlayer";
|
||||
|
||||
// AudioPlayer states
|
||||
public static int MEDIA_NONE = 0;
|
||||
public static int MEDIA_STARTING = 1;
|
||||
public static int MEDIA_RUNNING = 2;
|
||||
public static int MEDIA_PAUSED = 3;
|
||||
public static int MEDIA_STOPPED = 4;
|
||||
|
||||
// AudioPlayer message ids
|
||||
private static int MEDIA_STATE = 1;
|
||||
private static int MEDIA_DURATION = 2;
|
||||
private static int MEDIA_POSITION = 3;
|
||||
private static int MEDIA_ERROR = 9;
|
||||
|
||||
// Media error codes
|
||||
private static int MEDIA_ERR_NONE_ACTIVE = 0;
|
||||
private static int MEDIA_ERR_ABORTED = 1;
|
||||
private static int MEDIA_ERR_NETWORK = 2;
|
||||
private static int MEDIA_ERR_DECODE = 3;
|
||||
private static int MEDIA_ERR_NONE_SUPPORTED = 4;
|
||||
|
||||
private AudioHandler handler; // The AudioHandler object
|
||||
private String id; // The id of this player (used to identify Media object in JavaScript)
|
||||
private int state = MEDIA_NONE; // State of recording or playback
|
||||
private String audioFile = null; // File name to play or record to
|
||||
private float duration = -1; // Duration of audio
|
||||
|
||||
private MediaRecorder recorder = null; // Audio recording object
|
||||
private String tempFile = null; // Temporary recording file name
|
||||
|
||||
private MediaPlayer mPlayer = null; // Audio player object
|
||||
private boolean prepareOnly = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param handler The audio handler object
|
||||
* @param id The id of this audio player
|
||||
*/
|
||||
public AudioPlayer(AudioHandler handler, String id) {
|
||||
this.handler = handler;
|
||||
this.id = id;
|
||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
|
||||
} else {
|
||||
this.tempFile = "/data/data/" + handler.ctx.getActivity().getPackageName() + "/cache/tmprecording.mp3";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy player and stop audio playing or recording.
|
||||
*/
|
||||
public void destroy() {
|
||||
// Stop any play or record
|
||||
if (this.mPlayer != null) {
|
||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
||||
this.mPlayer.stop();
|
||||
this.setState(MEDIA_STOPPED);
|
||||
}
|
||||
this.mPlayer.release();
|
||||
this.mPlayer = null;
|
||||
}
|
||||
if (this.recorder != null) {
|
||||
this.stopRecording();
|
||||
this.recorder.release();
|
||||
this.recorder = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recording the specified file.
|
||||
*
|
||||
* @param file The name of the file
|
||||
*/
|
||||
public void startRecording(String file) {
|
||||
if (this.mPlayer != null) {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
||||
}
|
||||
// Make sure we're not already recording
|
||||
else if (this.recorder == null) {
|
||||
this.audioFile = file;
|
||||
this.recorder = new MediaRecorder();
|
||||
this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
|
||||
this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
|
||||
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
|
||||
this.recorder.setOutputFile(this.tempFile);
|
||||
try {
|
||||
this.recorder.prepare();
|
||||
this.recorder.start();
|
||||
this.setState(MEDIA_RUNNING);
|
||||
return;
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save temporary recorded file to specified name
|
||||
*
|
||||
* @param file
|
||||
*/
|
||||
public void moveFile(String file) {
|
||||
/* this is a hack to save the file as the specified name */
|
||||
File f = new File(this.tempFile);
|
||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
f.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||
+ File.separator + file));
|
||||
} else {
|
||||
f.renameTo(new File("/data/data/" + handler.ctx.getActivity().getPackageName() + "/cache/" + file));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording and save to the file specified when recording started.
|
||||
*/
|
||||
public void stopRecording() {
|
||||
if (this.recorder != null) {
|
||||
try{
|
||||
if (this.state == MEDIA_RUNNING) {
|
||||
this.recorder.stop();
|
||||
this.setState(MEDIA_STOPPED);
|
||||
}
|
||||
this.moveFile(this.audioFile);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start or resume playing audio file.
|
||||
*
|
||||
* @param file The name of the audio file.
|
||||
*/
|
||||
public void startPlaying(String file) {
|
||||
if (this.recorder != null) {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode.");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
||||
}
|
||||
|
||||
// If this is a new request to play audio, or stopped
|
||||
else if ((this.mPlayer == null) || (this.state == MEDIA_STOPPED)) {
|
||||
try {
|
||||
// If stopped, then reset player
|
||||
if (this.mPlayer != null) {
|
||||
this.mPlayer.reset();
|
||||
}
|
||||
// Otherwise, create a new one
|
||||
else {
|
||||
this.mPlayer = new MediaPlayer();
|
||||
}
|
||||
this.audioFile = file;
|
||||
|
||||
// If streaming file
|
||||
if (this.isStreaming(file)) {
|
||||
this.mPlayer.setDataSource(file);
|
||||
this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
this.setState(MEDIA_STARTING);
|
||||
this.mPlayer.setOnPreparedListener(this);
|
||||
this.mPlayer.prepareAsync();
|
||||
}
|
||||
|
||||
// If local file
|
||||
else {
|
||||
if (file.startsWith("/android_asset/")) {
|
||||
String f = file.substring(15);
|
||||
android.content.res.AssetFileDescriptor fd = this.handler.ctx.getActivity().getAssets().openFd(f);
|
||||
this.mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
|
||||
}
|
||||
else {
|
||||
File fp = new File(file);
|
||||
if (fp.exists()) {
|
||||
FileInputStream fileInputStream = new FileInputStream(file);
|
||||
this.mPlayer.setDataSource(fileInputStream.getFD());
|
||||
}
|
||||
else {
|
||||
this.mPlayer.setDataSource("/sdcard/" + file);
|
||||
}
|
||||
}
|
||||
this.setState(MEDIA_STARTING);
|
||||
this.mPlayer.setOnPreparedListener(this);
|
||||
this.mPlayer.prepare();
|
||||
|
||||
// Get duration
|
||||
this.duration = getDurationInSeconds();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
||||
}
|
||||
}
|
||||
|
||||
// If we have already have created an audio player
|
||||
else {
|
||||
|
||||
// If player has been paused, then resume playback
|
||||
if ((this.state == MEDIA_PAUSED) || (this.state == MEDIA_STARTING)) {
|
||||
this.mPlayer.start();
|
||||
this.setState(MEDIA_RUNNING);
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: " + this.state);
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek or jump to a new time in the track.
|
||||
*/
|
||||
public void seekToPlaying(int milliseconds) {
|
||||
if (this.mPlayer != null) {
|
||||
this.mPlayer.seekTo(milliseconds);
|
||||
Log.d(LOG_TAG, "Send a onStatus update for the new seek");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + milliseconds / 1000.0f + ");");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause playing.
|
||||
*/
|
||||
public void pausePlaying() {
|
||||
|
||||
// If playing, then pause
|
||||
if (this.state == MEDIA_RUNNING) {
|
||||
this.mPlayer.pause();
|
||||
this.setState(MEDIA_PAUSED);
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: " + this.state);
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop playing the audio file.
|
||||
*/
|
||||
public void stopPlaying() {
|
||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
||||
this.mPlayer.stop();
|
||||
this.setState(MEDIA_STOPPED);
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: " + this.state);
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be invoked when playback of a media source has completed.
|
||||
*
|
||||
* @param mPlayer The MediaPlayer that reached the end of the file
|
||||
*/
|
||||
public void onCompletion(MediaPlayer mPlayer) {
|
||||
this.setState(MEDIA_STOPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current position of playback.
|
||||
*
|
||||
* @return position in msec or -1 if not playing
|
||||
*/
|
||||
public long getCurrentPosition() {
|
||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
||||
int curPos = this.mPlayer.getCurrentPosition();
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + curPos / 1000.0f + ");");
|
||||
return curPos;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if playback file is streaming or local.
|
||||
* It is streaming if file name starts with "http://"
|
||||
*
|
||||
* @param file The file name
|
||||
* @return T=streaming, F=local
|
||||
*/
|
||||
public boolean isStreaming(String file) {
|
||||
if (file.contains("http://") || file.contains("https://")) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the audio file.
|
||||
*
|
||||
* @param file The name of the audio file.
|
||||
* @return The duration in msec.
|
||||
* -1=can't be determined
|
||||
* -2=not allowed
|
||||
*/
|
||||
public float getDuration(String file) {
|
||||
|
||||
// Can't get duration of recording
|
||||
if (this.recorder != null) {
|
||||
return (-2); // not allowed
|
||||
}
|
||||
|
||||
// If audio file already loaded and started, then return duration
|
||||
if (this.mPlayer != null) {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
// If no player yet, then create one
|
||||
else {
|
||||
this.prepareOnly = true;
|
||||
this.startPlaying(file);
|
||||
|
||||
// This will only return value for local, since streaming
|
||||
// file hasn't been read yet.
|
||||
return this.duration;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be invoked when the media source is ready for playback.
|
||||
*
|
||||
* @param mPlayer The MediaPlayer that is ready for playback
|
||||
*/
|
||||
public void onPrepared(MediaPlayer mPlayer) {
|
||||
// Listen for playback completion
|
||||
this.mPlayer.setOnCompletionListener(this);
|
||||
|
||||
// If start playing after prepared
|
||||
if (!this.prepareOnly) {
|
||||
|
||||
// Start playing
|
||||
this.mPlayer.start();
|
||||
|
||||
// Set player init flag
|
||||
this.setState(MEDIA_RUNNING);
|
||||
}
|
||||
|
||||
// Save off duration
|
||||
this.duration = getDurationInSeconds();
|
||||
this.prepareOnly = false;
|
||||
|
||||
// Send status notification to JavaScript
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_DURATION + "," + this.duration + ");");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* By default Android returns the length of audio in mills but we want seconds
|
||||
*
|
||||
* @return length of clip in seconds
|
||||
*/
|
||||
private float getDurationInSeconds() {
|
||||
return (this.mPlayer.getDuration() / 1000.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be invoked when there has been an error during an asynchronous operation
|
||||
* (other errors will throw exceptions at method call time).
|
||||
*
|
||||
* @param mPlayer the MediaPlayer the error pertains to
|
||||
* @param arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED)
|
||||
* @param arg2 an extra code, specific to the error.
|
||||
*/
|
||||
public boolean onError(MediaPlayer mPlayer, int arg1, int arg2) {
|
||||
Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")");
|
||||
|
||||
// TODO: Not sure if this needs to be sent?
|
||||
this.mPlayer.stop();
|
||||
this.mPlayer.release();
|
||||
|
||||
// Send error notification to JavaScript
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":" + arg1 + "});");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state and send it to JavaScript.
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
private void setState(int state) {
|
||||
if (this.state != state) {
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + state + ");");
|
||||
}
|
||||
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio state.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the volume for audio player
|
||||
*
|
||||
* @param volume
|
||||
*/
|
||||
public void setVolume(float volume) {
|
||||
this.mPlayer.setVolume(volume, volume);
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.util.Log;
|
||||
|
||||
public class BatteryListener extends Plugin {
|
||||
|
||||
private static final String LOG_TAG = "BatteryManager";
|
||||
|
||||
BroadcastReceiver receiver;
|
||||
|
||||
private String batteryCallbackId = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public BatteryListener() {
|
||||
this.receiver = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.INVALID_ACTION;
|
||||
String result = "Unsupported Operation: " + action;
|
||||
|
||||
if (action.equals("start")) {
|
||||
if (this.batteryCallbackId != null) {
|
||||
return new PluginResult(PluginResult.Status.ERROR, "Battery listener already running.");
|
||||
}
|
||||
this.batteryCallbackId = callbackId;
|
||||
|
||||
// We need to listen to power events to update battery status
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
if (this.receiver == null) {
|
||||
this.receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
updateBatteryInfo(intent);
|
||||
}
|
||||
};
|
||||
ctx.getActivity().registerReceiver(this.receiver, intentFilter);
|
||||
}
|
||||
|
||||
// Don't return any result now, since status results will be sent when events come in from broadcast receiver
|
||||
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||
pluginResult.setKeepCallback(true);
|
||||
return pluginResult;
|
||||
}
|
||||
|
||||
else if (action.equals("stop")) {
|
||||
removeBatteryListener();
|
||||
this.sendUpdate(new JSONObject(), false); // release status callback in JS side
|
||||
this.batteryCallbackId = null;
|
||||
return new PluginResult(PluginResult.Status.OK);
|
||||
}
|
||||
|
||||
return new PluginResult(status, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop battery receiver.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
removeBatteryListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the battery receiver and set it to null.
|
||||
*/
|
||||
private void removeBatteryListener() {
|
||||
if (this.receiver != null) {
|
||||
try {
|
||||
this.ctx.getActivity().unregisterReceiver(this.receiver);
|
||||
this.receiver = null;
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Error unregistering battery receiver: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSONObject with the current battery information
|
||||
*
|
||||
* @param batteryIntent the current battery information
|
||||
* @return a JSONObject containing the battery status information
|
||||
*/
|
||||
private JSONObject getBatteryInfo(Intent batteryIntent) {
|
||||
JSONObject obj = new JSONObject();
|
||||
try {
|
||||
obj.put("level", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, 0));
|
||||
obj.put("isPlugged", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_PLUGGED, -1) > 0 ? true : false);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the JavaScript side whenever the battery changes
|
||||
*
|
||||
* @param batteryIntent the current battery information
|
||||
* @return
|
||||
*/
|
||||
private void updateBatteryInfo(Intent batteryIntent) {
|
||||
sendUpdate(this.getBatteryInfo(batteryIntent), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new plugin result and send it back to JavaScript
|
||||
*
|
||||
* @param connection the network info to set as navigator.connection
|
||||
*/
|
||||
private void sendUpdate(JSONObject info, boolean keepCallback) {
|
||||
if (this.batteryCallbackId != null) {
|
||||
PluginResult result = new PluginResult(PluginResult.Status.OK, info);
|
||||
result.setKeepCallback(keepCallback);
|
||||
this.success(result, this.batteryCallbackId);
|
||||
}
|
||||
}
|
||||
}
|
||||
73
framework/src/org/apache/cordova/BuildHelper.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
/*
|
||||
* This is a utility class that allows us to get the BuildConfig variable, which is required
|
||||
* for the use of different providers. This is not guaranteed to work, and it's better for this
|
||||
* to be set in the build step in config.xml
|
||||
*
|
||||
*/
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
||||
public class BuildHelper {
|
||||
|
||||
|
||||
private static String TAG="BuildHelper";
|
||||
|
||||
/*
|
||||
* This needs to be implemented if you wish to use the Camera Plugin or other plugins
|
||||
* that read the Build Configuration.
|
||||
*
|
||||
* Thanks to Phil@Medtronic and Graham Borland for finding the answer and posting it to
|
||||
* StackOverflow. This is annoying as hell! However, this method does not work with
|
||||
* ProGuard, and you should use the config.xml to define the application_id
|
||||
*
|
||||
*/
|
||||
|
||||
public static Object getBuildConfigValue(Context ctx, String key)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> clazz = Class.forName(ctx.getClass().getPackage().getName() + ".BuildConfig");
|
||||
Field field = clazz.getField(key);
|
||||
return field.get(null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOG.d(TAG, "Unable to get the BuildConfig, is this built with ANT?");
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
LOG.d(TAG, key + " is not a valid field. Check your build.gradle");
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG.d(TAG, "Illegal Access Exception: Let's print a stack trace.");
|
||||
e.printStackTrace();
|
||||
} catch (NullPointerException e) {
|
||||
LOG.d(TAG, "Null Pointer Exception: Let's print a stack trace.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
142
framework/src/org/apache/cordova/CallbackContext.java
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import org.apache.cordova.CordovaWebView;
|
||||
import org.apache.cordova.PluginResult;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class CallbackContext {
|
||||
private static final String LOG_TAG = "CordovaPlugin";
|
||||
|
||||
private String callbackId;
|
||||
private CordovaWebView webView;
|
||||
protected boolean finished;
|
||||
private int changingThreads;
|
||||
|
||||
public CallbackContext(String callbackId, CordovaWebView webView) {
|
||||
this.callbackId = callbackId;
|
||||
this.webView = webView;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public boolean isChangingThreads() {
|
||||
return changingThreads > 0;
|
||||
}
|
||||
|
||||
public String getCallbackId() {
|
||||
return callbackId;
|
||||
}
|
||||
|
||||
public void sendPluginResult(PluginResult pluginResult) {
|
||||
synchronized (this) {
|
||||
if (finished) {
|
||||
LOG.w(LOG_TAG, "Attempted to send a second callback for ID: " + callbackId + "\nResult was: " + pluginResult.getMessage());
|
||||
return;
|
||||
} else {
|
||||
finished = !pluginResult.getKeepCallback();
|
||||
}
|
||||
}
|
||||
webView.sendPluginResult(pluginResult, callbackId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
*/
|
||||
public void success(JSONObject message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
*/
|
||||
public void success(String message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
*/
|
||||
public void success(JSONArray message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
*/
|
||||
public void success(byte[] message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
*/
|
||||
public void success(int message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*/
|
||||
public void success() {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.OK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for error callbacks that just returns the Status.ERROR by default
|
||||
*
|
||||
* @param message The message to add to the error result.
|
||||
*/
|
||||
public void error(JSONObject message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for error callbacks that just returns the Status.ERROR by default
|
||||
*
|
||||
* @param message The message to add to the error result.
|
||||
*/
|
||||
public void error(String message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for error callbacks that just returns the Status.ERROR by default
|
||||
*
|
||||
* @param message The message to add to the error result.
|
||||
*/
|
||||
public void error(int message) {
|
||||
sendPluginResult(new PluginResult(PluginResult.Status.ERROR, message));
|
||||
}
|
||||
}
|
||||
65
framework/src/org/apache/cordova/CallbackMap.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.util.Pair;
|
||||
import android.util.SparseArray;
|
||||
|
||||
/**
|
||||
* Provides a collection that maps unique request codes to CordovaPlugins and Integers.
|
||||
* Used to ensure that when plugins make requests for runtime permissions, those requests do not
|
||||
* collide with requests from other plugins that use the same request code value.
|
||||
*/
|
||||
public class CallbackMap {
|
||||
private int currentCallbackId = 0;
|
||||
private SparseArray<Pair<CordovaPlugin, Integer>> callbacks;
|
||||
|
||||
public CallbackMap() {
|
||||
this.callbacks = new SparseArray<Pair<CordovaPlugin, Integer>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a CordovaPlugin and request code and returns a new unique request code to use
|
||||
* in a permission request.
|
||||
*
|
||||
* @param receiver The plugin that is making the request
|
||||
* @param requestCode The original request code used by the plugin
|
||||
* @return A unique request code that can be used to retrieve this callback
|
||||
* with getAndRemoveCallback()
|
||||
*/
|
||||
public synchronized int registerCallback(CordovaPlugin receiver, int requestCode) {
|
||||
int mappedId = this.currentCallbackId++;
|
||||
callbacks.put(mappedId, new Pair<CordovaPlugin, Integer>(receiver, requestCode));
|
||||
return mappedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes a callback stored in the map using the mapped request code
|
||||
* obtained from registerCallback()
|
||||
*
|
||||
* @param mappedId The request code obtained from registerCallback()
|
||||
* @return The CordovaPlugin and orignal request code that correspond to the
|
||||
* given mappedCode
|
||||
*/
|
||||
public synchronized Pair<CordovaPlugin, Integer> getAndRemoveCallback(int mappedId) {
|
||||
Pair<CordovaPlugin, Integer> callback = callbacks.get(mappedId);
|
||||
callbacks.remove(mappedId);
|
||||
return callback;
|
||||
}
|
||||
}
|
||||
@@ -1,426 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* This class provides a way for Java to run JavaScript in the web page that has loaded Cordova.
|
||||
* The CallbackServer class implements an XHR server and a polling server with a list of JavaScript
|
||||
* statements that are to be executed on the web page.
|
||||
*
|
||||
* The process flow for XHR is:
|
||||
* 1. JavaScript makes an async XHR call.
|
||||
* 2. The server holds the connection open until data is available.
|
||||
* 3. The server writes the data to the client and closes the connection.
|
||||
* 4. The server immediately starts listening for the next XHR call.
|
||||
* 5. The client receives this XHR response, processes it.
|
||||
* 6. The client sends a new async XHR request.
|
||||
*
|
||||
* The CallbackServer class requires the following permission in Android manifest file
|
||||
* <uses-permission android:name="android.permission.INTERNET" />
|
||||
*
|
||||
* If the device has a proxy set, then XHR cannot be used, so polling must be used instead.
|
||||
* This can be determined by the client by calling CallbackServer.usePolling().
|
||||
*
|
||||
* The process flow for polling is:
|
||||
* 1. The client calls CallbackServer.getJavascript() to retrieve next statement.
|
||||
* 2. If statement available, then client processes it.
|
||||
* 3. The client repeats #1 in loop.
|
||||
*/
|
||||
public class CallbackServer implements Runnable {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String LOG_TAG = "CallbackServer";
|
||||
|
||||
/**
|
||||
* The list of JavaScript statements to be sent to JavaScript.
|
||||
*/
|
||||
private LinkedList<String> javascript;
|
||||
|
||||
/**
|
||||
* The port to listen on.
|
||||
*/
|
||||
private int port;
|
||||
|
||||
/**
|
||||
* The server thread.
|
||||
*/
|
||||
private Thread serverThread;
|
||||
|
||||
/**
|
||||
* Indicates the server is running.
|
||||
*/
|
||||
private boolean active;
|
||||
|
||||
/**
|
||||
* Indicates that the JavaScript statements list is empty
|
||||
*/
|
||||
private boolean empty;
|
||||
|
||||
/**
|
||||
* Indicates that polling should be used instead of XHR.
|
||||
*/
|
||||
private boolean usePolling = true;
|
||||
|
||||
/**
|
||||
* Security token to prevent other apps from accessing this callback server via XHR
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CallbackServer() {
|
||||
//Log.d(LOG_TAG, "CallbackServer()");
|
||||
this.active = false;
|
||||
this.empty = true;
|
||||
this.port = 0;
|
||||
this.javascript = new LinkedList<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init callback server and start XHR if running local app.
|
||||
*
|
||||
* If Cordova app is loaded from file://, then we can use XHR
|
||||
* otherwise we have to use polling due to cross-domain security restrictions.
|
||||
*
|
||||
* @param url The URL of the Cordova app being loaded
|
||||
*/
|
||||
public void init(String url) {
|
||||
//System.out.println("CallbackServer.start("+url+")");
|
||||
this.active = false;
|
||||
this.empty = true;
|
||||
this.port = 0;
|
||||
this.javascript = new LinkedList<String>();
|
||||
|
||||
// Determine if XHR or polling is to be used
|
||||
if ((url != null) && !url.startsWith("file://")) {
|
||||
this.usePolling = true;
|
||||
this.stopServer();
|
||||
}
|
||||
else if (android.net.Proxy.getDefaultHost() != null) {
|
||||
this.usePolling = true;
|
||||
this.stopServer();
|
||||
}
|
||||
else {
|
||||
this.usePolling = false;
|
||||
this.startServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-init when loading a new HTML page into webview.
|
||||
*
|
||||
* @param url The URL of the Cordova app being loaded
|
||||
*/
|
||||
public void reinit(String url) {
|
||||
this.stopServer();
|
||||
this.init(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if polling is being used instead of XHR.
|
||||
* @return
|
||||
*/
|
||||
public boolean usePolling() {
|
||||
return this.usePolling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the port that this server is running on.
|
||||
* @return
|
||||
*/
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the security token that this server requires when calling getJavascript().
|
||||
* @return
|
||||
*/
|
||||
public String getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the server on a new thread.
|
||||
*/
|
||||
public void startServer() {
|
||||
//Log.d(LOG_TAG, "CallbackServer.startServer()");
|
||||
this.active = false;
|
||||
|
||||
// Start server on new thread
|
||||
this.serverThread = new Thread(this);
|
||||
this.serverThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart the server on a new thread.
|
||||
*/
|
||||
public void restartServer() {
|
||||
|
||||
// Stop server
|
||||
this.stopServer();
|
||||
|
||||
// Start server again
|
||||
this.startServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start running the server.
|
||||
* This is called automatically when the server thread is started.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
// Start server
|
||||
try {
|
||||
this.active = true;
|
||||
String request;
|
||||
ServerSocket waitSocket = new ServerSocket(0);
|
||||
this.port = waitSocket.getLocalPort();
|
||||
//Log.d(LOG_TAG, "CallbackServer -- using port " +this.port);
|
||||
this.token = java.util.UUID.randomUUID().toString();
|
||||
//Log.d(LOG_TAG, "CallbackServer -- using token "+this.token);
|
||||
|
||||
while (this.active) {
|
||||
//Log.d(LOG_TAG, "CallbackServer: Waiting for data on socket");
|
||||
Socket connection = waitSocket.accept();
|
||||
BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()), 40);
|
||||
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
|
||||
request = xhrReader.readLine();
|
||||
String response = "";
|
||||
//Log.d(LOG_TAG, "CallbackServerRequest="+request);
|
||||
if (this.active && (request != null)) {
|
||||
if (request.contains("GET")) {
|
||||
|
||||
// Get requested file
|
||||
String[] requestParts = request.split(" ");
|
||||
|
||||
// Must have security token
|
||||
if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
|
||||
//Log.d(LOG_TAG, "CallbackServer -- Processing GET request");
|
||||
|
||||
// Wait until there is some data to send, or send empty data every 10 sec
|
||||
// to prevent XHR timeout on the client
|
||||
synchronized (this) {
|
||||
while (this.empty) {
|
||||
try {
|
||||
this.wait(10000); // prevent timeout from happening
|
||||
//Log.d(LOG_TAG, "CallbackServer>>> break <<<");
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If server is still running
|
||||
if (this.active) {
|
||||
|
||||
// If no data, then send 404 back to client before it times out
|
||||
if (this.empty) {
|
||||
//Log.d(LOG_TAG, "CallbackServer -- sending data 0");
|
||||
response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
|
||||
}
|
||||
else {
|
||||
//Log.d(LOG_TAG, "CallbackServer -- sending item");
|
||||
response = "HTTP/1.1 200 OK\r\n\r\n";
|
||||
String js = this.getJavascript();
|
||||
if (js != null) {
|
||||
response += encode(js, "UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
|
||||
}
|
||||
//Log.d(LOG_TAG, "CallbackServer: response="+response);
|
||||
//Log.d(LOG_TAG, "CallbackServer: closing output");
|
||||
output.writeBytes(response);
|
||||
output.flush();
|
||||
}
|
||||
output.close();
|
||||
xhrReader.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.active = false;
|
||||
//Log.d(LOG_TAG, "CallbackServer.startServer() - EXIT");
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop server.
|
||||
* This stops the thread that the server is running on.
|
||||
*/
|
||||
public void stopServer() {
|
||||
//Log.d(LOG_TAG, "CallbackServer.stopServer()");
|
||||
if (this.active) {
|
||||
this.active = false;
|
||||
|
||||
// Break out of server wait
|
||||
synchronized (this) {
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy
|
||||
*/
|
||||
public void destroy() {
|
||||
this.stopServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of JavaScript statements.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getSize() {
|
||||
synchronized (this) {
|
||||
int size = this.javascript.size();
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next JavaScript statement and remove from list.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getJavascript() {
|
||||
synchronized (this) {
|
||||
if (this.javascript.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
String statement = this.javascript.remove(0);
|
||||
if (this.javascript.size() == 0) {
|
||||
this.empty = true;
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JavaScript statement to the list.
|
||||
*
|
||||
* @param statement
|
||||
*/
|
||||
public void sendJavascript(String statement) {
|
||||
synchronized (this) {
|
||||
this.javascript.add(statement);
|
||||
this.empty = false;
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/* The Following code has been modified from original implementation of URLEncoder */
|
||||
|
||||
/* start */
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
static final String digits = "0123456789ABCDEF";
|
||||
|
||||
/**
|
||||
* This will encode the return value to JavaScript. We revert the encoding for
|
||||
* common characters that don't require encoding to reduce the size of the string
|
||||
* being passed to JavaScript.
|
||||
*
|
||||
* @param s to be encoded
|
||||
* @param enc encoding type
|
||||
* @return encoded string
|
||||
*/
|
||||
public static String encode(String s, String enc) throws UnsupportedEncodingException {
|
||||
if (s == null || enc == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
// check for UnsupportedEncodingException
|
||||
"".getBytes(enc);
|
||||
|
||||
// Guess a bit bigger for encoded form
|
||||
StringBuilder buf = new StringBuilder(s.length() + 16);
|
||||
int start = -1;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
|
||||
|| (ch >= '0' && ch <= '9')
|
||||
|| " .-*_'(),<>=?@[]{}:~\"\\/;!".indexOf(ch) > -1) {
|
||||
if (start >= 0) {
|
||||
convert(s.substring(start, i), buf, enc);
|
||||
start = -1;
|
||||
}
|
||||
if (ch != ' ') {
|
||||
buf.append(ch);
|
||||
} else {
|
||||
buf.append(' ');
|
||||
}
|
||||
} else {
|
||||
if (start < 0) {
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start >= 0) {
|
||||
convert(s.substring(start, s.length()), buf, enc);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static void convert(String s, StringBuilder buf, String enc) throws UnsupportedEncodingException {
|
||||
byte[] bytes = s.getBytes(enc);
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
buf.append('%');
|
||||
buf.append(digits.charAt((bytes[j] & 0xf0) >> 4));
|
||||
buf.append(digits.charAt(bytes[j] & 0xf));
|
||||
}
|
||||
}
|
||||
|
||||
/* end */
|
||||
}
|
||||
@@ -1,544 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
//import org.apache.cordova.api.CordovaInterface;
|
||||
import org.apache.cordova.api.LOG;
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
//import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
/**
|
||||
* This class launches the camera view, allows the user to take a picture, closes the camera view,
|
||||
* and returns the captured image. When the camera view is closed, the screen displayed before
|
||||
* the camera view was shown is redisplayed.
|
||||
*/
|
||||
public class CameraLauncher extends Plugin {
|
||||
|
||||
private static final int DATA_URL = 0; // Return base64 encoded string
|
||||
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
|
||||
|
||||
private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
|
||||
private static final int CAMERA = 1; // Take picture from camera
|
||||
private static final int SAVEDPHOTOALBUM = 2; // Choose image from picture library (same as PHOTOLIBRARY for Android)
|
||||
|
||||
private static final int PICTURE = 0; // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
|
||||
private static final int VIDEO = 1; // allow selection of video only, ONLY RETURNS URL
|
||||
private static final int ALLMEDIA = 2; // allow selection from all media types
|
||||
|
||||
private static final int JPEG = 0; // Take a picture of type JPEG
|
||||
private static final int PNG = 1; // Take a picture of type PNG
|
||||
private static final String GET_PICTURE = "Get Picture";
|
||||
private static final String GET_VIDEO = "Get Video";
|
||||
private static final String GET_All = "Get All";
|
||||
|
||||
private static final String LOG_TAG = "CameraLauncher";
|
||||
|
||||
private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
||||
private int targetWidth; // desired width of the image
|
||||
private int targetHeight; // desired height of the image
|
||||
private Uri imageUri; // Uri of captured image
|
||||
private int encodingType; // Type of encoding to use
|
||||
private int mediaType; // What type of media to retrieve
|
||||
|
||||
public String callbackId;
|
||||
private int numPics;
|
||||
|
||||
//This should never be null!
|
||||
//private CordovaInterface cordova;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CameraLauncher() {
|
||||
}
|
||||
|
||||
// public void setContext(CordovaInterface mCtx) {
|
||||
// super.setContext(mCtx);
|
||||
// if (CordovaInterface.class.isInstance(mCtx))
|
||||
// cordova = (CordovaInterface) mCtx;
|
||||
// else
|
||||
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
|
||||
// }
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
this.callbackId = callbackId;
|
||||
|
||||
try {
|
||||
if (action.equals("takePicture")) {
|
||||
int srcType = CAMERA;
|
||||
int destType = FILE_URI;
|
||||
this.targetHeight = 0;
|
||||
this.targetWidth = 0;
|
||||
this.encodingType = JPEG;
|
||||
this.mediaType = PICTURE;
|
||||
this.mQuality = 80;
|
||||
|
||||
this.mQuality = args.getInt(0);
|
||||
destType = args.getInt(1);
|
||||
srcType = args.getInt(2);
|
||||
this.targetWidth = args.getInt(3);
|
||||
this.targetHeight = args.getInt(4);
|
||||
this.encodingType = args.getInt(5);
|
||||
this.mediaType = args.getInt(6);
|
||||
|
||||
if (srcType == CAMERA) {
|
||||
this.takePicture(destType, encodingType);
|
||||
}
|
||||
else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
|
||||
this.getImage(srcType, destType);
|
||||
}
|
||||
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||
r.setKeepCallback(true);
|
||||
return r;
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Take a picture with the camera.
|
||||
* When an image is captured or the camera view is cancelled, the result is returned
|
||||
* in CordovaActivity.onActivityResult, which forwards the result to this.onActivityResult.
|
||||
*
|
||||
* The image can either be returned as a base64 string or a URI that points to the file.
|
||||
* To display base64 string in an img tag, set the source to:
|
||||
* img.src="data:image/jpeg;base64,"+result;
|
||||
* or to display URI in an img tag
|
||||
* img.src=result;
|
||||
*
|
||||
* @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
||||
* @param returnType Set the type of image to return.
|
||||
*/
|
||||
public void takePicture(int returnType, int encodingType) {
|
||||
// Save the number of images currently on disk for later
|
||||
this.numPics = queryImgDB().getCount();
|
||||
|
||||
// Display camera
|
||||
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
|
||||
|
||||
// Specify file so that large image is captured and returned
|
||||
// TODO: What if there isn't any external storage?
|
||||
File photo = createCaptureFile(encodingType);
|
||||
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
|
||||
this.imageUri = Uri.fromFile(photo);
|
||||
|
||||
if (this.ctx != null) {
|
||||
this.ctx.startActivityForResult((Plugin) this, intent, (CAMERA + 1) * 16 + returnType + 1);
|
||||
}
|
||||
// else
|
||||
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a file in the applications temporary directory based upon the supplied encoding.
|
||||
*
|
||||
* @param encodingType of the image to be taken
|
||||
* @return a File object pointing to the temporary picture
|
||||
*/
|
||||
private File createCaptureFile(int encodingType) {
|
||||
File photo = null;
|
||||
if (encodingType == JPEG) {
|
||||
photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.jpg");
|
||||
} else if (encodingType == PNG) {
|
||||
photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.png");
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
|
||||
}
|
||||
return photo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image from photo library.
|
||||
*
|
||||
* @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
||||
* @param srcType The album to get image from.
|
||||
* @param returnType Set the type of image to return.
|
||||
*/
|
||||
// TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
|
||||
public void getImage(int srcType, int returnType) {
|
||||
Intent intent = new Intent();
|
||||
String title = GET_PICTURE;
|
||||
if (this.mediaType == PICTURE) {
|
||||
intent.setType("image/*");
|
||||
}
|
||||
else if (this.mediaType == VIDEO) {
|
||||
intent.setType("video/*");
|
||||
title = GET_VIDEO;
|
||||
}
|
||||
else if (this.mediaType == ALLMEDIA) {
|
||||
// I wanted to make the type 'image/*, video/*' but this does not work on all versions
|
||||
// of android so I had to go with the wildcard search.
|
||||
intent.setType("*/*");
|
||||
title = GET_All;
|
||||
}
|
||||
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
if (this.ctx != null) {
|
||||
this.ctx.startActivityForResult((Plugin) this, Intent.createChooser(intent,
|
||||
new String(title)), (srcType + 1) * 16 + returnType + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the bitmap according to the requested size.
|
||||
*
|
||||
* @param bitmap The bitmap to scale.
|
||||
* @return Bitmap A new Bitmap object of the same bitmap after scaling.
|
||||
*/
|
||||
public Bitmap scaleBitmap(Bitmap bitmap) {
|
||||
int newWidth = this.targetWidth;
|
||||
int newHeight = this.targetHeight;
|
||||
int origWidth = bitmap.getWidth();
|
||||
int origHeight = bitmap.getHeight();
|
||||
|
||||
// If no new width or height were specified return the original bitmap
|
||||
if (newWidth <= 0 && newHeight <= 0) {
|
||||
return bitmap;
|
||||
}
|
||||
// Only the width was specified
|
||||
else if (newWidth > 0 && newHeight <= 0) {
|
||||
newHeight = (newWidth * origHeight) / origWidth;
|
||||
}
|
||||
// only the height was specified
|
||||
else if (newWidth <= 0 && newHeight > 0) {
|
||||
newWidth = (newHeight * origWidth) / origHeight;
|
||||
}
|
||||
// If the user specified both a positive width and height
|
||||
// (potentially different aspect ratio) then the width or height is
|
||||
// scaled so that the image fits while maintaining aspect ratio.
|
||||
// Alternatively, the specified width and height could have been
|
||||
// kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
|
||||
// would result in whitespace in the new image.
|
||||
else {
|
||||
double newRatio = newWidth / (double) newHeight;
|
||||
double origRatio = origWidth / (double) origHeight;
|
||||
|
||||
if (origRatio > newRatio) {
|
||||
newHeight = (newWidth * origHeight) / origWidth;
|
||||
} else if (origRatio < newRatio) {
|
||||
newWidth = (newHeight * origWidth) / origHeight;
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap retval = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
|
||||
bitmap.recycle();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the camera view exits.
|
||||
*
|
||||
* @param requestCode The request code originally supplied to startActivityForResult(),
|
||||
* allowing you to identify who this result came from.
|
||||
* @param resultCode The integer result code returned by the child activity through its setResult().
|
||||
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
|
||||
*/
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
|
||||
// Get src and dest types from request code
|
||||
int srcType = (requestCode / 16) - 1;
|
||||
int destType = (requestCode % 16) - 1;
|
||||
int rotate = 0;
|
||||
|
||||
// Create an ExifHelper to save the exif data that is lost during compression
|
||||
ExifHelper exif = new ExifHelper();
|
||||
try {
|
||||
if (this.encodingType == JPEG) {
|
||||
exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Pic.jpg");
|
||||
exif.readExifData();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// If CAMERA
|
||||
if (srcType == CAMERA) {
|
||||
// If image available
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
try {
|
||||
// Read in bitmap of captured image
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri);
|
||||
} catch (FileNotFoundException e) {
|
||||
Uri uri = intent.getData();
|
||||
android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver();
|
||||
bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
|
||||
}
|
||||
|
||||
bitmap = scaleBitmap(bitmap);
|
||||
|
||||
// If sending base64 image back
|
||||
if (destType == DATA_URL) {
|
||||
this.processPicture(bitmap);
|
||||
checkForDuplicateImage(DATA_URL);
|
||||
}
|
||||
|
||||
// If sending filename back
|
||||
else if (destType == FILE_URI) {
|
||||
// Create entry in media store for image
|
||||
// (Don't use insertImage() because it uses default compression setting of 50 - no way to change it)
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
|
||||
Uri uri = null;
|
||||
try {
|
||||
uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
LOG.d(LOG_TAG, "Can't write to external media storage.");
|
||||
try {
|
||||
uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
LOG.d(LOG_TAG, "Can't write to internal media storage.");
|
||||
this.failPicture("Error capturing image - no media storage found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add compressed version of captured image to returned media store Uri
|
||||
OutputStream os = this.ctx.getActivity().getContentResolver().openOutputStream(uri);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
|
||||
os.close();
|
||||
|
||||
// Restore exif data to file
|
||||
if (this.encodingType == JPEG) {
|
||||
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
|
||||
exif.writeExifData();
|
||||
}
|
||||
|
||||
// Send Uri back to JavaScript for viewing image
|
||||
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
|
||||
}
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
System.gc();
|
||||
|
||||
checkForDuplicateImage(FILE_URI);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
this.failPicture("Error capturing image.");
|
||||
}
|
||||
}
|
||||
|
||||
// If cancelled
|
||||
else if (resultCode == Activity.RESULT_CANCELED) {
|
||||
this.failPicture("Camera cancelled.");
|
||||
}
|
||||
|
||||
// If something else
|
||||
else {
|
||||
this.failPicture("Did not complete!");
|
||||
}
|
||||
}
|
||||
|
||||
// If retrieving photo from library
|
||||
else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Uri uri = intent.getData();
|
||||
android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver();
|
||||
|
||||
// If you ask for video or all media type you will automatically get back a file URI
|
||||
// and there will be no attempt to resize any returned data
|
||||
if (this.mediaType != PICTURE) {
|
||||
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
|
||||
}
|
||||
else {
|
||||
// If sending base64 image back
|
||||
if (destType == DATA_URL) {
|
||||
try {
|
||||
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
|
||||
String[] cols = { MediaStore.Images.Media.ORIENTATION };
|
||||
Cursor cursor = this.ctx.getActivity().getContentResolver().query(intent.getData(),
|
||||
cols,
|
||||
null, null, null);
|
||||
if (cursor != null) {
|
||||
cursor.moveToPosition(0);
|
||||
rotate = cursor.getInt(0);
|
||||
cursor.close();
|
||||
}
|
||||
if (rotate != 0) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setRotate(rotate);
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
}
|
||||
bitmap = scaleBitmap(bitmap);
|
||||
this.processPicture(bitmap);
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
System.gc();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
this.failPicture("Error retrieving image.");
|
||||
}
|
||||
}
|
||||
|
||||
// If sending filename back
|
||||
else if (destType == FILE_URI) {
|
||||
// Do we need to scale the returned file
|
||||
if (this.targetHeight > 0 && this.targetWidth > 0) {
|
||||
try {
|
||||
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
|
||||
bitmap = scaleBitmap(bitmap);
|
||||
|
||||
String fileName = DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/resize.jpg";
|
||||
OutputStream os = new FileOutputStream(fileName);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
|
||||
os.close();
|
||||
|
||||
// Restore exif data to file
|
||||
if (this.encodingType == JPEG) {
|
||||
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
|
||||
exif.writeExifData();
|
||||
}
|
||||
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
|
||||
// The resized image is cached by the app in order to get around this and not have to delete you
|
||||
// application cache I'm adding the current system time to the end of the file url.
|
||||
this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName + "?" + System.currentTimeMillis())), this.callbackId);
|
||||
System.gc();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.failPicture("Error retrieving image.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resultCode == Activity.RESULT_CANCELED) {
|
||||
this.failPicture("Selection cancelled.");
|
||||
}
|
||||
else {
|
||||
this.failPicture("Selection did not complete!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a cursor that can be used to determine how many images we have.
|
||||
*
|
||||
* @return a cursor
|
||||
*/
|
||||
private Cursor queryImgDB() {
|
||||
return this.ctx.getActivity().getContentResolver().query(
|
||||
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
new String[] { MediaStore.Images.Media._ID },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find out if we are in a situation where the Camera Intent adds to images
|
||||
* to the content store. If we are using a FILE_URI and the number of images in the DB
|
||||
* increases by 2 we have a duplicate, when using a DATA_URL the number is 1.
|
||||
*
|
||||
* @param type FILE_URI or DATA_URL
|
||||
*/
|
||||
private void checkForDuplicateImage(int type) {
|
||||
int diff = 1;
|
||||
Cursor cursor = queryImgDB();
|
||||
int currentNumOfImages = cursor.getCount();
|
||||
|
||||
if (type == FILE_URI) {
|
||||
diff = 2;
|
||||
}
|
||||
|
||||
// delete the duplicate file if the difference is 2 for file URI or 1 for Data URL
|
||||
if ((currentNumOfImages - numPics) == diff) {
|
||||
cursor.moveToLast();
|
||||
int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1;
|
||||
Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id);
|
||||
this.ctx.getActivity().getContentResolver().delete(uri, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress bitmap using jpeg, convert to Base64 encoded string, and return to JavaScript.
|
||||
*
|
||||
* @param bitmap
|
||||
*/
|
||||
public void processPicture(Bitmap bitmap) {
|
||||
ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
|
||||
try {
|
||||
if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) {
|
||||
byte[] code = jpeg_data.toByteArray();
|
||||
byte[] output = Base64.encodeBase64(code);
|
||||
String js_out = new String(output);
|
||||
this.success(new PluginResult(PluginResult.Status.OK, js_out), this.callbackId);
|
||||
js_out = null;
|
||||
output = null;
|
||||
code = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.failPicture("Error compressing image.");
|
||||
}
|
||||
jpeg_data = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send error message to JavaScript.
|
||||
*
|
||||
* @param err
|
||||
*/
|
||||
public void failPicture(String err) {
|
||||
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
|
||||
}
|
||||
}
|
||||
@@ -1,408 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.cordova.api.LOG;
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
public class Capture extends Plugin {
|
||||
|
||||
private static final String VIDEO_3GPP = "video/3gpp";
|
||||
private static final String VIDEO_MP4 = "video/mp4";
|
||||
private static final String AUDIO_3GPP = "audio/3gpp";
|
||||
private static final String IMAGE_JPEG = "image/jpeg";
|
||||
|
||||
private static final int CAPTURE_AUDIO = 0; // Constant for capture audio
|
||||
private static final int CAPTURE_IMAGE = 1; // Constant for capture image
|
||||
private static final int CAPTURE_VIDEO = 2; // Constant for capture video
|
||||
private static final String LOG_TAG = "Capture";
|
||||
|
||||
private static final int CAPTURE_INTERNAL_ERR = 0;
|
||||
// private static final int CAPTURE_APPLICATION_BUSY = 1;
|
||||
// private static final int CAPTURE_INVALID_ARGUMENT = 2;
|
||||
private static final int CAPTURE_NO_MEDIA_FILES = 3;
|
||||
private static final int CAPTURE_NOT_SUPPORTED = 20;
|
||||
|
||||
private String callbackId; // The ID of the callback to be invoked with our result
|
||||
private long limit; // the number of pics/vids/clips to take
|
||||
private double duration; // optional duration parameter for video recording
|
||||
private JSONArray results; // The array of results to be returned to the user
|
||||
private Uri imageUri; // Uri of captured image
|
||||
|
||||
//private CordovaInterface cordova;
|
||||
|
||||
// public void setContext(Context mCtx)
|
||||
// {
|
||||
// if (CordovaInterface.class.isInstance(mCtx))
|
||||
// cordova = (CordovaInterface) mCtx;
|
||||
// else
|
||||
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
|
||||
// }
|
||||
|
||||
@Override
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
this.callbackId = callbackId;
|
||||
this.limit = 1;
|
||||
this.duration = 0.0f;
|
||||
this.results = new JSONArray();
|
||||
|
||||
JSONObject options = args.optJSONObject(0);
|
||||
if (options != null) {
|
||||
limit = options.optLong("limit", 1);
|
||||
duration = options.optDouble("duration", 0.0f);
|
||||
}
|
||||
|
||||
if (action.equals("getFormatData")) {
|
||||
try {
|
||||
JSONObject obj = getFormatData(args.getString(0), args.getString(1));
|
||||
return new PluginResult(PluginResult.Status.OK, obj);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.ERROR);
|
||||
}
|
||||
}
|
||||
else if (action.equals("captureAudio")) {
|
||||
this.captureAudio();
|
||||
}
|
||||
else if (action.equals("captureImage")) {
|
||||
this.captureImage();
|
||||
}
|
||||
else if (action.equals("captureVideo")) {
|
||||
this.captureVideo(duration);
|
||||
}
|
||||
|
||||
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||
r.setKeepCallback(true);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the media data file data depending on it's mime type
|
||||
*
|
||||
* @param filePath path to the file
|
||||
* @param mimeType of the file
|
||||
* @return a MediaFileData object
|
||||
*/
|
||||
private JSONObject getFormatData(String filePath, String mimeType) {
|
||||
JSONObject obj = new JSONObject();
|
||||
try {
|
||||
// setup defaults
|
||||
obj.put("height", 0);
|
||||
obj.put("width", 0);
|
||||
obj.put("bitrate", 0);
|
||||
obj.put("duration", 0);
|
||||
obj.put("codecs", "");
|
||||
|
||||
// If the mimeType isn't set the rest will fail
|
||||
// so let's see if we can determine it.
|
||||
if (mimeType == null || mimeType.equals("")) {
|
||||
mimeType = FileUtils.getMimeType(filePath);
|
||||
}
|
||||
Log.d(LOG_TAG, "Mime type = " + mimeType);
|
||||
|
||||
if (mimeType.equals(IMAGE_JPEG) || filePath.endsWith(".jpg")) {
|
||||
obj = getImageData(filePath, obj);
|
||||
}
|
||||
else if (mimeType.endsWith(AUDIO_3GPP)) {
|
||||
obj = getAudioVideoData(filePath, obj, false);
|
||||
}
|
||||
else if (mimeType.equals(VIDEO_3GPP) || mimeType.equals(VIDEO_MP4)) {
|
||||
obj = getAudioVideoData(filePath, obj, true);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Error: setting media file data object");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Image specific attributes
|
||||
*
|
||||
* @param filePath path to the file
|
||||
* @param obj represents the Media File Data
|
||||
* @return a JSONObject that represents the Media File Data
|
||||
* @throws JSONException
|
||||
*/
|
||||
private JSONObject getImageData(String filePath, JSONObject obj) throws JSONException {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeFile(FileUtils.stripFileProtocol(filePath), options);
|
||||
obj.put("height", options.outHeight);
|
||||
obj.put("width", options.outWidth);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Image specific attributes
|
||||
*
|
||||
* @param filePath path to the file
|
||||
* @param obj represents the Media File Data
|
||||
* @param video if true get video attributes as well
|
||||
* @return a JSONObject that represents the Media File Data
|
||||
* @throws JSONException
|
||||
*/
|
||||
private JSONObject getAudioVideoData(String filePath, JSONObject obj, boolean video) throws JSONException {
|
||||
MediaPlayer player = new MediaPlayer();
|
||||
try {
|
||||
player.setDataSource(filePath);
|
||||
player.prepare();
|
||||
obj.put("duration", player.getDuration() / 1000);
|
||||
if (video) {
|
||||
obj.put("height", player.getVideoHeight());
|
||||
obj.put("width", player.getVideoWidth());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.d(LOG_TAG, "Error: loading video file");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an intent to capture audio. Result handled by onActivityResult()
|
||||
*/
|
||||
private void captureAudio() {
|
||||
Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION);
|
||||
|
||||
this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an intent to capture images. Result handled by onActivityResult()
|
||||
*/
|
||||
private void captureImage() {
|
||||
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
|
||||
// Specify file so that large image is captured and returned
|
||||
File photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Capture.jpg");
|
||||
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
|
||||
this.imageUri = Uri.fromFile(photo);
|
||||
|
||||
this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an intent to capture video. Result handled by onActivityResult()
|
||||
*/
|
||||
private void captureVideo(double duration) {
|
||||
Intent intent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
|
||||
// Introduced in API 8
|
||||
//intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration);
|
||||
|
||||
this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the video view exits.
|
||||
*
|
||||
* @param requestCode The request code originally supplied to startActivityForResult(),
|
||||
* allowing you to identify who this result came from.
|
||||
* @param resultCode The integer result code returned by the child activity through its setResult().
|
||||
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
|
||||
* @throws JSONException
|
||||
*/
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
|
||||
// Result received okay
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
// An audio clip was requested
|
||||
if (requestCode == CAPTURE_AUDIO) {
|
||||
// Get the uri of the audio clip
|
||||
Uri data = intent.getData();
|
||||
// create a file object from the uri
|
||||
results.put(createMediaFile(data));
|
||||
|
||||
if (results.length() >= limit) {
|
||||
// Send Uri back to JavaScript for listening to audio
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
} else {
|
||||
// still need to capture more audio clips
|
||||
captureAudio();
|
||||
}
|
||||
} else if (requestCode == CAPTURE_IMAGE) {
|
||||
// For some reason if I try to do:
|
||||
// Uri data = intent.getData();
|
||||
// It crashes in the emulator and on my phone with a null pointer exception
|
||||
// To work around it I had to grab the code from CameraLauncher.java
|
||||
try {
|
||||
// Create an ExifHelper to save the exif data that is lost during compression
|
||||
ExifHelper exif = new ExifHelper();
|
||||
exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Capture.jpg");
|
||||
exif.readExifData();
|
||||
|
||||
// Read in bitmap of captured image
|
||||
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri);
|
||||
|
||||
// Create entry in media store for image
|
||||
// (Don't use insertImage() because it uses default compression setting of 50 - no way to change it)
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, IMAGE_JPEG);
|
||||
Uri uri = null;
|
||||
try {
|
||||
uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
LOG.d(LOG_TAG, "Can't write to external media storage.");
|
||||
try {
|
||||
uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
LOG.d(LOG_TAG, "Can't write to internal media storage.");
|
||||
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add compressed version of captured image to returned media store Uri
|
||||
OutputStream os = this.ctx.getActivity().getContentResolver().openOutputStream(uri);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
|
||||
os.close();
|
||||
|
||||
bitmap.recycle();
|
||||
bitmap = null;
|
||||
System.gc();
|
||||
|
||||
// Restore exif data to file
|
||||
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
|
||||
exif.writeExifData();
|
||||
|
||||
// Add image to results
|
||||
results.put(createMediaFile(uri));
|
||||
|
||||
if (results.length() >= limit) {
|
||||
// Send Uri back to JavaScript for viewing image
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
} else {
|
||||
// still need to capture more images
|
||||
captureImage();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image."));
|
||||
}
|
||||
} else if (requestCode == CAPTURE_VIDEO) {
|
||||
// Get the uri of the video clip
|
||||
Uri data = intent.getData();
|
||||
// create a file object from the uri
|
||||
results.put(createMediaFile(data));
|
||||
|
||||
if (results.length() >= limit) {
|
||||
// Send Uri back to JavaScript for viewing video
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
} else {
|
||||
// still need to capture more video clips
|
||||
captureVideo(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If canceled
|
||||
else if (resultCode == Activity.RESULT_CANCELED) {
|
||||
// If we have partial results send them back to the user
|
||||
if (results.length() > 0) {
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
}
|
||||
// user canceled the action
|
||||
else {
|
||||
this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Canceled."));
|
||||
}
|
||||
}
|
||||
// If something else
|
||||
else {
|
||||
// If we have partial results send them back to the user
|
||||
if (results.length() > 0) {
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
}
|
||||
// something bad happened
|
||||
else {
|
||||
this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Did not complete!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSONObject that represents a File from the Uri
|
||||
*
|
||||
* @param data the Uri of the audio/image/video
|
||||
* @return a JSONObject that represents a File
|
||||
* @throws IOException
|
||||
*/
|
||||
private JSONObject createMediaFile(Uri data) {
|
||||
File fp = new File(FileUtils.getRealPathFromURI(data, this.ctx));
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
try {
|
||||
// File properties
|
||||
obj.put("name", fp.getName());
|
||||
obj.put("fullPath", "file://" + fp.getAbsolutePath());
|
||||
// Because of an issue with MimeTypeMap.getMimeTypeFromExtension() all .3gpp files
|
||||
// are reported as video/3gpp. I'm doing this hacky check of the URI to see if it
|
||||
// is stored in the audio or video content store.
|
||||
if (fp.getAbsoluteFile().toString().endsWith(".3gp") || fp.getAbsoluteFile().toString().endsWith(".3gpp")) {
|
||||
if (data.toString().contains("/audio/")) {
|
||||
obj.put("type", AUDIO_3GPP);
|
||||
} else {
|
||||
obj.put("type", VIDEO_3GPP);
|
||||
}
|
||||
} else {
|
||||
obj.put("type", FileUtils.getMimeType(fp.getAbsolutePath()));
|
||||
}
|
||||
|
||||
obj.put("lastModifiedDate", fp.lastModified());
|
||||
obj.put("size", fp.length());
|
||||
} catch (JSONException e) {
|
||||
// this will never happen
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private JSONObject createErrorObject(int code, String message) {
|
||||
JSONObject obj = new JSONObject();
|
||||
try {
|
||||
obj.put("code", code);
|
||||
obj.put("message", message);
|
||||
} catch (JSONException e) {
|
||||
// This will never happen
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send error message to JavaScript.
|
||||
*
|
||||
* @param err
|
||||
*/
|
||||
public void fail(JSONObject err) {
|
||||
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cordova.api.CordovaInterface;
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* This class listens to the compass sensor and stores the latest heading value.
|
||||
*/
|
||||
public class CompassListener extends Plugin implements SensorEventListener {
|
||||
|
||||
public static int STOPPED = 0;
|
||||
public static int STARTING = 1;
|
||||
public static int RUNNING = 2;
|
||||
public static int ERROR_FAILED_TO_START = 3;
|
||||
|
||||
public long TIMEOUT = 30000; // Timeout in msec to shut off listener
|
||||
|
||||
int status; // status of listener
|
||||
float heading; // most recent heading value
|
||||
long timeStamp; // time of most recent value
|
||||
long lastAccessTime; // time the value was last retrieved
|
||||
int accuracy; // accuracy of the sensor
|
||||
|
||||
private SensorManager sensorManager;// Sensor manager
|
||||
Sensor mSensor; // Compass sensor returned by sensor manager
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CompassListener() {
|
||||
this.heading = 0;
|
||||
this.timeStamp = 0;
|
||||
this.setStatus(CompassListener.STOPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context of the Command. This can then be used to do things like
|
||||
* get file paths associated with the Activity.
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(CordovaInterface ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
if (action.equals("start")) {
|
||||
this.start();
|
||||
}
|
||||
else if (action.equals("stop")) {
|
||||
this.stop();
|
||||
}
|
||||
else if (action.equals("getStatus")) {
|
||||
int i = this.getStatus();
|
||||
return new PluginResult(status, i);
|
||||
}
|
||||
else if (action.equals("getHeading")) {
|
||||
// If not running, then this is an async call, so don't worry about waiting
|
||||
if (this.status != CompassListener.RUNNING) {
|
||||
int r = this.start();
|
||||
if (r == CompassListener.ERROR_FAILED_TO_START) {
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START);
|
||||
}
|
||||
// Wait until running
|
||||
long timeout = 2000;
|
||||
while ((this.status == STARTING) && (timeout > 0)) {
|
||||
timeout = timeout - 100;
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (timeout == 0) {
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START);
|
||||
}
|
||||
}
|
||||
return new PluginResult(status, getCompassHeading());
|
||||
}
|
||||
else if (action.equals("setTimeout")) {
|
||||
this.setTimeout(args.getLong(0));
|
||||
}
|
||||
else if (action.equals("getTimeout")) {
|
||||
long l = this.getTimeout();
|
||||
return new PluginResult(status, l);
|
||||
} else {
|
||||
// Unsupported action
|
||||
return new PluginResult(PluginResult.Status.INVALID_ACTION);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies if action to be executed returns a value and should be run synchronously.
|
||||
*
|
||||
* @param action The action to execute
|
||||
* @return T=returns value
|
||||
*/
|
||||
public boolean isSynch(String action) {
|
||||
if (action.equals("getStatus")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("getHeading")) {
|
||||
// Can only return value if RUNNING
|
||||
if (this.status == CompassListener.RUNNING) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (action.equals("getTimeout")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when listener is to be shut down and object is being destroyed.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Start listening for compass sensor.
|
||||
*
|
||||
* @return status of listener
|
||||
*/
|
||||
public int start() {
|
||||
|
||||
// If already starting or running, then just return
|
||||
if ((this.status == CompassListener.RUNNING) || (this.status == CompassListener.STARTING)) {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
// Get compass sensor from sensor manager
|
||||
@SuppressWarnings("deprecation")
|
||||
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
|
||||
|
||||
// If found, then register as listener
|
||||
if (list != null && list.size() > 0) {
|
||||
this.mSensor = list.get(0);
|
||||
this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
this.lastAccessTime = System.currentTimeMillis();
|
||||
this.setStatus(CompassListener.STARTING);
|
||||
}
|
||||
|
||||
// If error, then set status to error
|
||||
else {
|
||||
this.setStatus(CompassListener.ERROR_FAILED_TO_START);
|
||||
}
|
||||
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop listening to compass sensor.
|
||||
*/
|
||||
public void stop() {
|
||||
if (this.status != CompassListener.STOPPED) {
|
||||
this.sensorManager.unregisterListener(this);
|
||||
}
|
||||
this.setStatus(CompassListener.STOPPED);
|
||||
}
|
||||
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
/**
|
||||
* Sensor listener event.
|
||||
*
|
||||
* @param SensorEvent event
|
||||
*/
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
|
||||
// We only care about the orientation as far as it refers to Magnetic North
|
||||
float heading = event.values[0];
|
||||
|
||||
// Save heading
|
||||
this.timeStamp = System.currentTimeMillis();
|
||||
this.heading = heading;
|
||||
this.setStatus(CompassListener.RUNNING);
|
||||
|
||||
// If heading hasn't been read for TIMEOUT time, then turn off compass sensor to save power
|
||||
if ((this.timeStamp - this.lastAccessTime) > this.TIMEOUT) {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status of compass sensor.
|
||||
*
|
||||
* @return status
|
||||
*/
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the most recent compass heading.
|
||||
*
|
||||
* @return heading
|
||||
*/
|
||||
public float getHeading() {
|
||||
this.lastAccessTime = System.currentTimeMillis();
|
||||
return this.heading;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout to turn off compass sensor if getHeading() hasn't been called.
|
||||
*
|
||||
* @param timeout Timeout in msec.
|
||||
*/
|
||||
public void setTimeout(long timeout) {
|
||||
this.TIMEOUT = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timeout to turn off compass sensor if getHeading() hasn't been called.
|
||||
*
|
||||
* @return timeout in msec
|
||||
*/
|
||||
public long getTimeout() {
|
||||
return this.TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the status and send it to JavaScript.
|
||||
* @param status
|
||||
*/
|
||||
private void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the CompassHeading JSON object to be returned to JavaScript
|
||||
*
|
||||
* @return a compass heading
|
||||
*/
|
||||
private JSONObject getCompassHeading() {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
try {
|
||||
obj.put("magneticHeading", this.getHeading());
|
||||
obj.put("trueHeading", this.getHeading());
|
||||
// Since the magnetic and true heading are always the same our and accuracy
|
||||
// is defined as the difference between true and magnetic always return zero
|
||||
obj.put("headingAccuracy", 0);
|
||||
obj.put("timestamp", this.timeStamp);
|
||||
} catch (JSONException e) {
|
||||
// Should never happen
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
}
|
||||
71
framework/src/org/apache/cordova/Config.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
@Deprecated // Use AllowList, CordovaPrefences, etc. directly.
|
||||
public class Config {
|
||||
private static final String TAG = "Config";
|
||||
|
||||
static ConfigXmlParser parser;
|
||||
|
||||
private Config() {
|
||||
}
|
||||
|
||||
public static void init(Activity action) {
|
||||
parser = new ConfigXmlParser();
|
||||
parser.parse(action);
|
||||
//TODO: Add feature to bring this back. Some preferences should be overridden by intents, but not all
|
||||
parser.getPreferences().setPreferencesBundle(action.getIntent().getExtras());
|
||||
}
|
||||
|
||||
// Intended to be used for testing only; creates an empty configuration.
|
||||
public static void init() {
|
||||
if (parser == null) {
|
||||
parser = new ConfigXmlParser();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getStartUrl() {
|
||||
if (parser == null) {
|
||||
return "file:///android_asset/www/index.html";
|
||||
}
|
||||
return parser.getLaunchUrl();
|
||||
}
|
||||
|
||||
public static String getErrorUrl() {
|
||||
return parser.getPreferences().getString("errorurl", null);
|
||||
}
|
||||
|
||||
public static List<PluginEntry> getPluginEntries() {
|
||||
return parser.getPluginEntries();
|
||||
}
|
||||
|
||||
public static CordovaPreferences getPreferences() {
|
||||
return parser.getPreferences();
|
||||
}
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return parser != null;
|
||||
}
|
||||
}
|
||||
166
framework/src/org/apache/cordova/ConfigXmlParser.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public class ConfigXmlParser {
|
||||
private static String TAG = "ConfigXmlParser";
|
||||
|
||||
private String launchUrl = null;
|
||||
private CordovaPreferences prefs = new CordovaPreferences();
|
||||
private ArrayList<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
|
||||
|
||||
public CordovaPreferences getPreferences() {
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public ArrayList<PluginEntry> getPluginEntries() {
|
||||
return pluginEntries;
|
||||
}
|
||||
|
||||
public String getLaunchUrl() {
|
||||
if (launchUrl == null) {
|
||||
launchUrl = "https://" + this.prefs.getString("hostname", "localhost");
|
||||
}
|
||||
|
||||
if (this.prefs.getBoolean("AndroidInsecureFileModeEnabled", false)) {
|
||||
launchUrl = "file:///android_asset/www/index.html";
|
||||
}
|
||||
|
||||
return launchUrl;
|
||||
}
|
||||
|
||||
public void parse(Context action) {
|
||||
// First checking the class namespace for config.xml
|
||||
int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName());
|
||||
if (id == 0) {
|
||||
// If we couldn't find config.xml there, we'll look in the namespace from AndroidManifest.xml
|
||||
id = action.getResources().getIdentifier("config", "xml", action.getPackageName());
|
||||
if (id == 0) {
|
||||
LOG.e(TAG, "res/xml/config.xml is missing!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pluginEntries.add(
|
||||
new PluginEntry(
|
||||
AllowListPlugin.PLUGIN_NAME,
|
||||
"org.apache.cordova.AllowListPlugin",
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
parse(action.getResources().getXml(id));
|
||||
}
|
||||
|
||||
boolean insideFeature = false;
|
||||
String service = "", pluginClass = "", paramType = "";
|
||||
boolean onload = false;
|
||||
|
||||
public void parse(XmlPullParser xml) {
|
||||
int eventType = -1;
|
||||
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
handleStartTag(xml);
|
||||
}
|
||||
else if (eventType == XmlPullParser.END_TAG)
|
||||
{
|
||||
handleEndTag(xml);
|
||||
}
|
||||
try {
|
||||
eventType = xml.next();
|
||||
} catch (XmlPullParserException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleStartTag(XmlPullParser xml) {
|
||||
String strNode = xml.getName();
|
||||
if (strNode.equals("feature")) {
|
||||
//Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc)
|
||||
//Set the bit for reading params
|
||||
insideFeature = true;
|
||||
service = xml.getAttributeValue(null, "name");
|
||||
}
|
||||
else if (insideFeature && strNode.equals("param")) {
|
||||
paramType = xml.getAttributeValue(null, "name");
|
||||
if (paramType.equals("service")) // check if it is using the older service param
|
||||
service = xml.getAttributeValue(null, "value");
|
||||
else if (paramType.equals("package") || paramType.equals("android-package"))
|
||||
pluginClass = xml.getAttributeValue(null,"value");
|
||||
else if (paramType.equals("onload"))
|
||||
onload = "true".equals(xml.getAttributeValue(null, "value"));
|
||||
}
|
||||
else if (strNode.equals("preference")) {
|
||||
String name = xml.getAttributeValue(null, "name").toLowerCase(Locale.ENGLISH);
|
||||
String value = xml.getAttributeValue(null, "value");
|
||||
prefs.set(name, value);
|
||||
}
|
||||
else if (strNode.equals("content")) {
|
||||
String src = xml.getAttributeValue(null, "src");
|
||||
if (src != null) {
|
||||
setStartUrl(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleEndTag(XmlPullParser xml) {
|
||||
String strNode = xml.getName();
|
||||
if (strNode.equals("feature")) {
|
||||
pluginEntries.add(new PluginEntry(service, pluginClass, onload));
|
||||
|
||||
service = "";
|
||||
pluginClass = "";
|
||||
insideFeature = false;
|
||||
onload = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setStartUrl(String src) {
|
||||
Pattern schemeRegex = Pattern.compile("^[a-z-]+://");
|
||||
Matcher matcher = schemeRegex.matcher(src);
|
||||
if (matcher.find()) {
|
||||
launchUrl = src;
|
||||
} else {
|
||||
if (src.charAt(0) == '/') {
|
||||
src = src.substring(1);
|
||||
}
|
||||
if (this.prefs.getBoolean("AndroidInsecureFileModeEnabled", false)) {
|
||||
launchUrl = "file:///android_asset/www/" + src;
|
||||
} else {
|
||||
launchUrl = "https://" + this.prefs.getString("hostname", "localhost") + "/" + src;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import org.apache.cordova.api.CordovaInterface;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* This abstract class defines SDK-independent API for communication with
|
||||
* Contacts Provider. The actual implementation used by the application depends
|
||||
* on the level of API available on the device. If the API level is Cupcake or
|
||||
* Donut, we want to use the {@link ContactAccessorSdk3_4} class. If it is
|
||||
* Eclair or higher, we want to use {@link ContactAccessorSdk5}.
|
||||
*/
|
||||
public abstract class ContactAccessor {
|
||||
|
||||
protected final String LOG_TAG = "ContactsAccessor";
|
||||
protected CordovaInterface mApp;
|
||||
protected WebView mView;
|
||||
|
||||
/**
|
||||
* Check to see if the data associated with the key is required to
|
||||
* be populated in the Contact object.
|
||||
* @param key
|
||||
* @param map created by running buildPopulationSet.
|
||||
* @return true if the key data is required
|
||||
*/
|
||||
protected boolean isRequired(String key, HashMap<String,Boolean> map) {
|
||||
Boolean retVal = map.get(key);
|
||||
return (retVal == null) ? false : retVal.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a hash map of what data needs to be populated in the Contact object
|
||||
* @param fields the list of fields to populate
|
||||
* @return the hash map of required data
|
||||
*/
|
||||
protected HashMap<String,Boolean> buildPopulationSet(JSONArray fields) {
|
||||
HashMap<String,Boolean> map = new HashMap<String,Boolean>();
|
||||
|
||||
String key;
|
||||
try {
|
||||
if (fields.length() == 1 && fields.getString(0).equals("*")) {
|
||||
map.put("displayName", true);
|
||||
map.put("name", true);
|
||||
map.put("nickname", true);
|
||||
map.put("phoneNumbers", true);
|
||||
map.put("emails", true);
|
||||
map.put("addresses", true);
|
||||
map.put("ims", true);
|
||||
map.put("organizations", true);
|
||||
map.put("birthday", true);
|
||||
map.put("note", true);
|
||||
map.put("urls", true);
|
||||
map.put("photos", true);
|
||||
map.put("categories", true);
|
||||
}
|
||||
else {
|
||||
for (int i=0; i<fields.length(); i++) {
|
||||
key = fields.getString(i);
|
||||
if (key.startsWith("displayName")) {
|
||||
map.put("displayName", true);
|
||||
}
|
||||
else if (key.startsWith("name")) {
|
||||
map.put("displayName", true);
|
||||
map.put("name", true);
|
||||
}
|
||||
else if (key.startsWith("nickname")) {
|
||||
map.put("nickname", true);
|
||||
}
|
||||
else if (key.startsWith("phoneNumbers")) {
|
||||
map.put("phoneNumbers", true);
|
||||
}
|
||||
else if (key.startsWith("emails")) {
|
||||
map.put("emails", true);
|
||||
}
|
||||
else if (key.startsWith("addresses")) {
|
||||
map.put("addresses", true);
|
||||
}
|
||||
else if (key.startsWith("ims")) {
|
||||
map.put("ims", true);
|
||||
}
|
||||
else if (key.startsWith("organizations")) {
|
||||
map.put("organizations", true);
|
||||
}
|
||||
else if (key.startsWith("birthday")) {
|
||||
map.put("birthday", true);
|
||||
}
|
||||
else if (key.startsWith("note")) {
|
||||
map.put("note", true);
|
||||
}
|
||||
else if (key.startsWith("urls")) {
|
||||
map.put("urls", true);
|
||||
}
|
||||
else if (key.startsWith("photos")) {
|
||||
map.put("photos", true);
|
||||
}
|
||||
else if (key.startsWith("categories")) {
|
||||
map.put("categories", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get a string from a JSON object. Saves a
|
||||
* lot of try/catch writing.
|
||||
* If the property is not found in the object null will be returned.
|
||||
*
|
||||
* @param obj contact object to search
|
||||
* @param property to be looked up
|
||||
* @return The value of the property
|
||||
*/
|
||||
protected String getJsonString(JSONObject obj, String property) {
|
||||
String value = null;
|
||||
try {
|
||||
if (obj != null) {
|
||||
value = obj.getString(property);
|
||||
if (value.equals("null")) {
|
||||
Log.d(LOG_TAG, property + " is string called 'null'");
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Could not get = " + e.getMessage());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles adding a JSON Contact object into the database.
|
||||
* @return TODO
|
||||
*/
|
||||
public abstract String save(JSONObject contact);
|
||||
|
||||
/**
|
||||
* Handles searching through SDK-specific contacts API.
|
||||
*/
|
||||
public abstract JSONArray search(JSONArray filter, JSONObject options);
|
||||
|
||||
/**
|
||||
* Handles searching through SDK-specific contacts API.
|
||||
* @throws JSONException
|
||||
*/
|
||||
public abstract JSONObject getContactById(String id) throws JSONException;
|
||||
|
||||
/**
|
||||
* Handles removing a contact from the database.
|
||||
*/
|
||||
public abstract boolean remove(String id);
|
||||
|
||||
/**
|
||||
* A class that represents the where clause to be used in the database query
|
||||
*/
|
||||
class WhereOptions {
|
||||
private String where;
|
||||
private String[] whereArgs;
|
||||
public void setWhere(String where) {
|
||||
this.where = where;
|
||||
}
|
||||
public String getWhere() {
|
||||
return where;
|
||||
}
|
||||
public void setWhereArgs(String[] whereArgs) {
|
||||
this.whereArgs = whereArgs;
|
||||
}
|
||||
public String[] getWhereArgs() {
|
||||
return whereArgs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.api.Plugin;
|
||||
import org.apache.cordova.api.PluginResult;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import android.util.Log;
|
||||
|
||||
public class ContactManager extends Plugin {
|
||||
|
||||
private ContactAccessor contactAccessor;
|
||||
private static final String LOG_TAG = "Contact Query";
|
||||
|
||||
public static final int UNKNOWN_ERROR = 0;
|
||||
public static final int INVALID_ARGUMENT_ERROR = 1;
|
||||
public static final int TIMEOUT_ERROR = 2;
|
||||
public static final int PENDING_OPERATION_ERROR = 3;
|
||||
public static final int IO_ERROR = 4;
|
||||
public static final int NOT_SUPPORTED_ERROR = 5;
|
||||
public static final int PERMISSION_DENIED_ERROR = 20;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ContactManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
|
||||
/**
|
||||
* Check to see if we are on an Android 1.X device. If we are return an error as we
|
||||
* do not support this as of Cordova 1.0.
|
||||
*/
|
||||
if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
|
||||
return new PluginResult(PluginResult.Status.ERROR, ContactManager.NOT_SUPPORTED_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only create the contactAccessor after we check the Android version or the program will crash
|
||||
* older phones.
|
||||
*/
|
||||
if (this.contactAccessor == null) {
|
||||
this.contactAccessor = new ContactAccessorSdk5(this.webView, this.ctx);
|
||||
}
|
||||
|
||||
try {
|
||||
if (action.equals("search")) {
|
||||
JSONArray res = contactAccessor.search(args.getJSONArray(0), args.optJSONObject(1));
|
||||
return new PluginResult(status, res);
|
||||
}
|
||||
else if (action.equals("save")) {
|
||||
String id = contactAccessor.save(args.getJSONObject(0));
|
||||
if (id != null) {
|
||||
JSONObject res = contactAccessor.getContactById(id);
|
||||
if (res != null) {
|
||||
return new PluginResult(status, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (action.equals("remove")) {
|
||||
if (contactAccessor.remove(args.getString(0))) {
|
||||
return new PluginResult(status, result);
|
||||
}
|
||||
}
|
||||
// If we get to this point an error has occurred
|
||||
return new PluginResult(PluginResult.Status.ERROR, ContactManager.UNKNOWN_ERROR);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
530
framework/src/org/apache/cordova/CordovaActivity.java
Executable file
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* This class is the main Android activity that represents the Cordova
|
||||
* application. It should be extended by the user to load the specific
|
||||
* html file that contains the application.
|
||||
*
|
||||
* As an example:
|
||||
*
|
||||
* <pre>
|
||||
* package org.apache.cordova.examples;
|
||||
*
|
||||
* import android.os.Bundle;
|
||||
* import org.apache.cordova.*;
|
||||
*
|
||||
* public class Example extends CordovaActivity {
|
||||
* @Override
|
||||
* public void onCreate(Bundle savedInstanceState) {
|
||||
* super.onCreate(savedInstanceState);
|
||||
* super.init();
|
||||
* // Load your application
|
||||
* loadUrl(launchUrl);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Cordova xml configuration: Cordova uses a configuration file at
|
||||
* res/xml/config.xml to specify its settings. See "The config.xml File"
|
||||
* guide in cordova-docs at http://cordova.apache.org/docs for the documentation
|
||||
* for the configuration. The use of the set*Property() methods is
|
||||
* deprecated in favor of the config.xml file.
|
||||
*
|
||||
*/
|
||||
public class CordovaActivity extends AppCompatActivity {
|
||||
public static String TAG = "CordovaActivity";
|
||||
|
||||
// The webview for our app
|
||||
protected CordovaWebView appView;
|
||||
|
||||
private static int ACTIVITY_STARTING = 0;
|
||||
private static int ACTIVITY_RUNNING = 1;
|
||||
private static int ACTIVITY_EXITING = 2;
|
||||
|
||||
// Keep app running when pause is received. (default = true)
|
||||
// If true, then the JavaScript and native code continue to run in the background
|
||||
// when another application (activity) is started.
|
||||
protected boolean keepRunning = true;
|
||||
|
||||
// Flag to keep immersive mode if set to fullscreen
|
||||
protected boolean immersiveMode;
|
||||
|
||||
// Read from config.xml:
|
||||
protected CordovaPreferences preferences;
|
||||
protected String launchUrl;
|
||||
protected ArrayList<PluginEntry> pluginEntries;
|
||||
protected CordovaInterfaceImpl cordovaInterface;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
// need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
|
||||
loadConfig();
|
||||
|
||||
String logLevel = preferences.getString("loglevel", "ERROR");
|
||||
LOG.setLogLevel(logLevel);
|
||||
|
||||
LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
|
||||
LOG.d(TAG, "CordovaActivity.onCreate()");
|
||||
|
||||
if (!preferences.getBoolean("ShowTitle", false)) {
|
||||
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
}
|
||||
|
||||
if (preferences.getBoolean("SetFullscreen", false)) {
|
||||
LOG.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
|
||||
preferences.set("Fullscreen", true);
|
||||
}
|
||||
if (preferences.getBoolean("Fullscreen", false)) {
|
||||
// NOTE: use the FullscreenNotImmersive configuration key to set the activity in a REAL full screen
|
||||
// (as was the case in previous cordova versions)
|
||||
if (!preferences.getBoolean("FullscreenNotImmersive", false)) {
|
||||
immersiveMode = true;
|
||||
// The splashscreen plugin needs the flags set before we're focused to prevent
|
||||
// the nav and title bars from flashing in.
|
||||
setImmersiveUiVisibility();
|
||||
} else {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
} else {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
cordovaInterface = makeCordovaInterface();
|
||||
if (savedInstanceState != null) {
|
||||
cordovaInterface.restoreInstanceState(savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
appView = makeWebView();
|
||||
createViews();
|
||||
if (!appView.isInitialized()) {
|
||||
appView.init(cordovaInterface, pluginEntries, preferences);
|
||||
}
|
||||
cordovaInterface.onCordovaInit(appView.getPluginManager());
|
||||
|
||||
// Wire the hardware volume controls to control media if desired.
|
||||
String volumePref = preferences.getString("DefaultVolumeStream", "");
|
||||
if ("media".equals(volumePref.toLowerCase(Locale.ENGLISH))) {
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void loadConfig() {
|
||||
ConfigXmlParser parser = new ConfigXmlParser();
|
||||
parser.parse(this);
|
||||
preferences = parser.getPreferences();
|
||||
preferences.setPreferencesBundle(getIntent().getExtras());
|
||||
launchUrl = parser.getLaunchUrl();
|
||||
pluginEntries = parser.getPluginEntries();
|
||||
Config.parser = parser;
|
||||
}
|
||||
|
||||
//Suppressing warnings in AndroidStudio
|
||||
@SuppressWarnings({"deprecation", "ResourceType"})
|
||||
protected void createViews() {
|
||||
//Why are we setting a constant as the ID? This should be investigated
|
||||
appView.getView().setId(100);
|
||||
appView.getView().setLayoutParams(new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
setContentView(appView.getView());
|
||||
|
||||
if (preferences.contains("BackgroundColor")) {
|
||||
try {
|
||||
int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
|
||||
// Background of activity:
|
||||
appView.getView().setBackgroundColor(backgroundColor);
|
||||
}
|
||||
catch (NumberFormatException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
appView.getView().requestFocusFromTouch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the default web view object.
|
||||
* <p/>
|
||||
* Override this to customize the webview that is used.
|
||||
*/
|
||||
protected CordovaWebView makeWebView() {
|
||||
return new CordovaWebViewImpl(makeWebViewEngine());
|
||||
}
|
||||
|
||||
protected CordovaWebViewEngine makeWebViewEngine() {
|
||||
return CordovaWebViewImpl.createEngine(this, preferences);
|
||||
}
|
||||
|
||||
protected CordovaInterfaceImpl makeCordovaInterface() {
|
||||
return new CordovaInterfaceImpl(this) {
|
||||
@Override
|
||||
public Object onMessage(String id, Object data) {
|
||||
// Plumb this to CordovaActivity.onMessage for backwards compatibility
|
||||
return CordovaActivity.this.onMessage(id, data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*/
|
||||
public void loadUrl(String url) {
|
||||
if (appView == null) {
|
||||
init();
|
||||
}
|
||||
|
||||
// If keepRunning
|
||||
this.keepRunning = preferences.getBoolean("KeepRunning", true);
|
||||
|
||||
appView.loadUrlIntoView(url, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the system is about to start resuming a previous activity.
|
||||
*/
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
LOG.d(TAG, "Paused the activity.");
|
||||
|
||||
if (this.appView != null) {
|
||||
// CB-9382 If there is an activity that started for result and main activity is waiting for callback
|
||||
// result, we shoudn't stop WebView Javascript timers, as activity for result might be using them
|
||||
boolean keepRunning = this.keepRunning || this.cordovaInterface.activityResultCallback != null;
|
||||
this.appView.handlePause(keepRunning);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity receives a new intent
|
||||
*/
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
//Forward to plugins
|
||||
if (this.appView != null)
|
||||
this.appView.onNewIntent(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity will start interacting with the user.
|
||||
*/
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
LOG.d(TAG, "Resumed the activity.");
|
||||
|
||||
if (this.appView == null) {
|
||||
return;
|
||||
}
|
||||
if (! this.getWindow().getDecorView().hasFocus()) {
|
||||
// Force window to have focus, so application always
|
||||
// receive user input. Workaround for some devices (Samsung Galaxy Note 3 at least)
|
||||
this.getWindow().getDecorView().requestFocus();
|
||||
}
|
||||
|
||||
this.appView.handleResume(this.keepRunning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is no longer visible to the user.
|
||||
*/
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
LOG.d(TAG, "Stopped the activity.");
|
||||
|
||||
if (this.appView == null) {
|
||||
return;
|
||||
}
|
||||
this.appView.handleStop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is becoming visible to the user.
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
LOG.d(TAG, "Started the activity.");
|
||||
|
||||
if (this.appView == null) {
|
||||
return;
|
||||
}
|
||||
this.appView.handleStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* The final call you receive before your activity is destroyed.
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
LOG.d(TAG, "CordovaActivity.onDestroy()");
|
||||
super.onDestroy();
|
||||
|
||||
if (this.appView != null) {
|
||||
appView.handleDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when view focus is changed
|
||||
*/
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus && immersiveMode) {
|
||||
setImmersiveUiVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
protected void setImmersiveUiVisibility() {
|
||||
final int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
|
||||
getWindow().getDecorView().setSystemUiVisibility(uiOptions);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
|
||||
// Capture requestCode here so that it is captured in the setActivityResultCallback() case.
|
||||
cordovaInterface.setActivityResultRequestCode(requestCode);
|
||||
super.startActivityForResult(intent, requestCode, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an activity you launched exits, giving you the requestCode you started it with,
|
||||
* the resultCode it returned, and any additional data from it.
|
||||
*
|
||||
* @param requestCode The request code originally supplied to startActivityForResult(),
|
||||
* allowing you to identify who this result came from.
|
||||
* @param resultCode The integer result code returned by the child activity through its setResult().
|
||||
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
LOG.d(TAG, "Incoming Result. Request code = " + requestCode);
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
cordovaInterface.onActivityResult(requestCode, resultCode, intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
|
||||
* The errorCode parameter corresponds to one of the ERROR_* constants.
|
||||
*
|
||||
* @param errorCode The error code corresponding to an ERROR_* value.
|
||||
* @param description A String describing the error.
|
||||
* @param failingUrl The url that failed to load.
|
||||
*/
|
||||
public void onReceivedError(final int errorCode, final String description, final String failingUrl) {
|
||||
final CordovaActivity me = this;
|
||||
|
||||
// If errorUrl specified, then load it
|
||||
final String errorUrl = preferences.getString("errorUrl", null);
|
||||
if ((errorUrl != null) && (!failingUrl.equals(errorUrl)) && (appView != null)) {
|
||||
// Load URL on UI thread
|
||||
me.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
me.appView.showWebPage(errorUrl, false, true, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
// If not, then display error dialog
|
||||
else {
|
||||
final boolean exit = !(errorCode == WebViewClient.ERROR_HOST_LOOKUP);
|
||||
me.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
if (exit) {
|
||||
me.appView.getView().setVisibility(View.GONE);
|
||||
me.displayError("Application Error", description + " (" + failingUrl + ")", "OK", exit);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an error dialog and optionally exit application.
|
||||
*/
|
||||
public void displayError(final String title, final String message, final String button, final boolean exit) {
|
||||
final CordovaActivity me = this;
|
||||
me.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(me);
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle(title);
|
||||
dlg.setCancelable(false);
|
||||
dlg.setPositiveButton(button,
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
if (exit) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
dlg.create();
|
||||
dlg.show();
|
||||
} catch (Exception e) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook in Cordova for menu plugins
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
if (appView != null) {
|
||||
appView.getPluginManager().postMessage("onCreateOptionsMenu", menu);
|
||||
}
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
if (appView != null) {
|
||||
appView.getPluginManager().postMessage("onPrepareOptionsMenu", menu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (appView != null) {
|
||||
appView.getPluginManager().postMessage("onOptionsItemSelected", item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a message is sent to plugin.
|
||||
*
|
||||
* @param id The message id
|
||||
* @param data The message data
|
||||
* @return Object or null
|
||||
*/
|
||||
public Object onMessage(String id, Object data) {
|
||||
if ("onReceivedError".equals(id)) {
|
||||
JSONObject d = (JSONObject) data;
|
||||
try {
|
||||
this.onReceivedError(d.getInt("errorCode"), d.getString("description"), d.getString("url"));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if ("exit".equals(id)) {
|
||||
finish();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
cordovaInterface.onSaveInstanceState(outState);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when the device configuration changes while your activity is running.
|
||||
*
|
||||
* @param newConfig The new device configuration
|
||||
*/
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
if (this.appView == null) {
|
||||
return;
|
||||
}
|
||||
PluginManager pm = this.appView.getPluginManager();
|
||||
if (pm != null) {
|
||||
pm.onConfigurationChanged(newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when the user grants permissions
|
||||
*
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String permissions[],
|
||||
int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
try
|
||||
{
|
||||
cordovaInterface.onRequestPermissionResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
catch (JSONException e)
|
||||
{
|
||||
LOG.d(TAG, "JSONException: Parameters fed into the method are not valid");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
113
framework/src/org/apache/cordova/CordovaArgs.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
public class CordovaArgs {
|
||||
private JSONArray baseArgs;
|
||||
|
||||
public CordovaArgs(JSONArray args) {
|
||||
this.baseArgs = args;
|
||||
}
|
||||
|
||||
|
||||
// Pass through the basics to the base args.
|
||||
public Object get(int index) throws JSONException {
|
||||
return baseArgs.get(index);
|
||||
}
|
||||
|
||||
public boolean getBoolean(int index) throws JSONException {
|
||||
return baseArgs.getBoolean(index);
|
||||
}
|
||||
|
||||
public double getDouble(int index) throws JSONException {
|
||||
return baseArgs.getDouble(index);
|
||||
}
|
||||
|
||||
public int getInt(int index) throws JSONException {
|
||||
return baseArgs.getInt(index);
|
||||
}
|
||||
|
||||
public JSONArray getJSONArray(int index) throws JSONException {
|
||||
return baseArgs.getJSONArray(index);
|
||||
}
|
||||
|
||||
public JSONObject getJSONObject(int index) throws JSONException {
|
||||
return baseArgs.getJSONObject(index);
|
||||
}
|
||||
|
||||
public long getLong(int index) throws JSONException {
|
||||
return baseArgs.getLong(index);
|
||||
}
|
||||
|
||||
public String getString(int index) throws JSONException {
|
||||
return baseArgs.getString(index);
|
||||
}
|
||||
|
||||
|
||||
public Object opt(int index) {
|
||||
return baseArgs.opt(index);
|
||||
}
|
||||
|
||||
public boolean optBoolean(int index) {
|
||||
return baseArgs.optBoolean(index);
|
||||
}
|
||||
|
||||
public double optDouble(int index) {
|
||||
return baseArgs.optDouble(index);
|
||||
}
|
||||
|
||||
public int optInt(int index) {
|
||||
return baseArgs.optInt(index);
|
||||
}
|
||||
|
||||
public JSONArray optJSONArray(int index) {
|
||||
return baseArgs.optJSONArray(index);
|
||||
}
|
||||
|
||||
public JSONObject optJSONObject(int index) {
|
||||
return baseArgs.optJSONObject(index);
|
||||
}
|
||||
|
||||
public long optLong(int index) {
|
||||
return baseArgs.optLong(index);
|
||||
}
|
||||
|
||||
public String optString(int index) {
|
||||
return baseArgs.optString(index);
|
||||
}
|
||||
|
||||
public boolean isNull(int index) {
|
||||
return baseArgs.isNull(index);
|
||||
}
|
||||
|
||||
|
||||
// The interesting custom helpers.
|
||||
public byte[] getArrayBuffer(int index) throws JSONException {
|
||||
String encoded = baseArgs.getString(index);
|
||||
return Base64.decode(encoded, Base64.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
186
framework/src/org/apache/cordova/CordovaBridge.java
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
* Contains APIs that the JS can call. All functions in here should also have
|
||||
* an equivalent entry in CordovaChromeClient.java, and be added to
|
||||
* cordova-js/lib/android/plugin/android/promptbasednativeapi.js
|
||||
*/
|
||||
public class CordovaBridge {
|
||||
private static final String LOG_TAG = "CordovaBridge";
|
||||
private PluginManager pluginManager;
|
||||
private NativeToJsMessageQueue jsMessageQueue;
|
||||
private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread.
|
||||
|
||||
public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
|
||||
this.pluginManager = pluginManager;
|
||||
this.jsMessageQueue = jsMessageQueue;
|
||||
}
|
||||
|
||||
public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
|
||||
if (!verifySecret("exec()", bridgeSecret)) {
|
||||
return null;
|
||||
}
|
||||
// If the arguments weren't received, send a message back to JS. It will switch bridge modes and try again. See CB-2666.
|
||||
// We send a message meant specifically for this case. It starts with "@" so no other message can be encoded into the same string.
|
||||
if (arguments == null) {
|
||||
return "@Null arguments.";
|
||||
}
|
||||
|
||||
jsMessageQueue.setPaused(true);
|
||||
try {
|
||||
// Tell the resourceApi what thread the JS is running on.
|
||||
CordovaResourceApi.jsThread = Thread.currentThread();
|
||||
|
||||
pluginManager.exec(service, action, callbackId, arguments);
|
||||
String ret = null;
|
||||
if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
|
||||
ret = jsMessageQueue.popAndEncode(false);
|
||||
}
|
||||
return ret;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
} finally {
|
||||
jsMessageQueue.setPaused(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void jsSetNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
|
||||
if (!verifySecret("setNativeToJsBridgeMode()", bridgeSecret)) {
|
||||
return;
|
||||
}
|
||||
jsMessageQueue.setBridgeMode(value);
|
||||
}
|
||||
|
||||
public String jsRetrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
|
||||
if (!verifySecret("retrieveJsMessages()", bridgeSecret)) {
|
||||
return null;
|
||||
}
|
||||
return jsMessageQueue.popAndEncode(fromOnlineEvent);
|
||||
}
|
||||
|
||||
private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException {
|
||||
if (!jsMessageQueue.isBridgeEnabled()) {
|
||||
if (bridgeSecret == -1) {
|
||||
LOG.d(LOG_TAG, action + " call made before bridge was enabled.");
|
||||
} else {
|
||||
LOG.d(LOG_TAG, "Ignoring " + action + " from previous page load.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Bridge secret wrong and bridge not due to it being from the previous page.
|
||||
if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) {
|
||||
LOG.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!");
|
||||
clearBridgeSecret();
|
||||
throw new IllegalAccessException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Called on page transitions */
|
||||
void clearBridgeSecret() {
|
||||
expectedBridgeSecret = -1;
|
||||
}
|
||||
|
||||
public boolean isSecretEstablished() {
|
||||
return expectedBridgeSecret != -1;
|
||||
}
|
||||
|
||||
/** Called by cordova.js to initialize the bridge. */
|
||||
//On old Androids SecureRandom isn't really secure, this is the least of your problems if
|
||||
//you're running Android 4.3 and below in 2017
|
||||
int generateBridgeSecret() {
|
||||
SecureRandom randGen = new SecureRandom();
|
||||
expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE);
|
||||
return expectedBridgeSecret;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
jsMessageQueue.reset();
|
||||
clearBridgeSecret();
|
||||
}
|
||||
|
||||
public String promptOnJsPrompt(String origin, String message, String defaultValue) {
|
||||
if (defaultValue != null && defaultValue.startsWith("gap:")) {
|
||||
JSONArray array;
|
||||
try {
|
||||
array = new JSONArray(defaultValue.substring(4));
|
||||
int bridgeSecret = array.getInt(0);
|
||||
String service = array.getString(1);
|
||||
String action = array.getString(2);
|
||||
String callbackId = array.getString(3);
|
||||
String r = jsExec(bridgeSecret, service, action, callbackId, message);
|
||||
return r == null ? "" : r;
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// Sets the native->JS bridge mode.
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
|
||||
try {
|
||||
int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
|
||||
jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
|
||||
} catch (NumberFormatException e){
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// Polling for JavaScript messages
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
|
||||
int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
|
||||
try {
|
||||
String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message));
|
||||
return r == null ? "" : r;
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
|
||||
// Protect against random iframes being able to talk through the bridge.
|
||||
// Trust only pages which the app would have been allowed to navigate to anyway.
|
||||
if (pluginManager.shouldAllowBridgeAccess(origin)) {
|
||||
// Enable the bridge
|
||||
int bridgeMode = Integer.parseInt(defaultValue.substring(9));
|
||||
jsMessageQueue.setBridgeMode(bridgeMode);
|
||||
// Tell JS the bridge secret.
|
||||
int secret = generateBridgeSecret();
|
||||
return ""+secret;
|
||||
} else {
|
||||
LOG.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,332 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.api.CordovaInterface;
|
||||
import org.apache.cordova.api.LOG;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
//import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
//import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.KeyEvent;
|
||||
//import android.view.View;
|
||||
import android.webkit.ConsoleMessage;
|
||||
import android.webkit.JsPromptResult;
|
||||
import android.webkit.JsResult;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebStorage;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.GeolocationPermissions.Callback;
|
||||
import android.widget.EditText;
|
||||
|
||||
/**
|
||||
* This class is the WebChromeClient that implements callbacks for our web view.
|
||||
*/
|
||||
public class CordovaChromeClient extends WebChromeClient {
|
||||
|
||||
private String TAG = "CordovaLog";
|
||||
private long MAX_QUOTA = 100 * 1024 * 1024;
|
||||
private CordovaInterface ctx;
|
||||
private CordovaWebView appView;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
public CordovaChromeClient(CordovaInterface ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ctx
|
||||
* @param app
|
||||
*/
|
||||
public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) {
|
||||
this.ctx = ctx;
|
||||
this.appView = app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param view
|
||||
*/
|
||||
public void setWebView(CordovaWebView view) {
|
||||
this.appView = view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the client to display a javascript alert dialog.
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @param message
|
||||
* @param result
|
||||
*/
|
||||
@Override
|
||||
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity());
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle("Alert");
|
||||
//Don't let alerts break the back button
|
||||
dlg.setCancelable(true);
|
||||
dlg.setPositiveButton(android.R.string.ok,
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.confirm();
|
||||
}
|
||||
});
|
||||
dlg.setOnCancelListener(
|
||||
new DialogInterface.OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
result.confirm();
|
||||
}
|
||||
});
|
||||
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||
//DO NOTHING
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
result.confirm();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
});
|
||||
dlg.create();
|
||||
dlg.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the client to display a confirm dialog to the user.
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @param message
|
||||
* @param result
|
||||
*/
|
||||
@Override
|
||||
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity());
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle("Confirm");
|
||||
dlg.setCancelable(true);
|
||||
dlg.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.confirm();
|
||||
}
|
||||
});
|
||||
dlg.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.cancel();
|
||||
}
|
||||
});
|
||||
dlg.setOnCancelListener(
|
||||
new DialogInterface.OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
result.cancel();
|
||||
}
|
||||
});
|
||||
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||
//DO NOTHING
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
result.cancel();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
});
|
||||
dlg.create();
|
||||
dlg.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the client to display a prompt dialog to the user.
|
||||
* If the client returns true, WebView will assume that the client will
|
||||
* handle the prompt dialog and call the appropriate JsPromptResult method.
|
||||
*
|
||||
* Since we are hacking prompts for our own purposes, we should not be using them for
|
||||
* this purpose, perhaps we should hack console.log to do this instead!
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @param message
|
||||
* @param defaultValue
|
||||
* @param result
|
||||
*/
|
||||
@Override
|
||||
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
|
||||
|
||||
// Security check to make sure any requests are coming from the page initially
|
||||
// loaded in webview and not another loaded in an iframe.
|
||||
boolean reqOk = false;
|
||||
if (url.startsWith("file://") || url.indexOf(this.appView.baseUrl) == 0 || this.appView.isUrlWhiteListed(url)) {
|
||||
reqOk = true;
|
||||
}
|
||||
|
||||
// Calling PluginManager.exec() to call a native service using
|
||||
// prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
|
||||
if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
|
||||
JSONArray array;
|
||||
try {
|
||||
array = new JSONArray(defaultValue.substring(4));
|
||||
String service = array.getString(0);
|
||||
String action = array.getString(1);
|
||||
String callbackId = array.getString(2);
|
||||
boolean async = array.getBoolean(3);
|
||||
String r = this.appView.pluginManager.exec(service, action, callbackId, message, async);
|
||||
result.confirm(r);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Polling for JavaScript messages
|
||||
else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
|
||||
String r = this.appView.callbackServer.getJavascript();
|
||||
result.confirm(r);
|
||||
}
|
||||
|
||||
// Do NO-OP so older code doesn't display dialog
|
||||
else if (defaultValue != null && defaultValue.equals("gap_init:")) {
|
||||
result.confirm("OK");
|
||||
}
|
||||
|
||||
// Calling into CallbackServer
|
||||
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
|
||||
String r = "";
|
||||
if (message.equals("usePolling")) {
|
||||
r = "" + this.appView.callbackServer.usePolling();
|
||||
}
|
||||
else if (message.equals("restartServer")) {
|
||||
this.appView.callbackServer.restartServer();
|
||||
}
|
||||
else if (message.equals("getPort")) {
|
||||
r = Integer.toString(this.appView.callbackServer.getPort());
|
||||
}
|
||||
else if (message.equals("getToken")) {
|
||||
r = this.appView.callbackServer.getToken();
|
||||
}
|
||||
result.confirm(r);
|
||||
}
|
||||
|
||||
// Show dialog
|
||||
else {
|
||||
final JsPromptResult res = result;
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity());
|
||||
dlg.setMessage(message);
|
||||
final EditText input = new EditText(this.ctx.getActivity());
|
||||
if (defaultValue != null) {
|
||||
input.setText(defaultValue);
|
||||
}
|
||||
dlg.setView(input);
|
||||
dlg.setCancelable(false);
|
||||
dlg.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
String usertext = input.getText().toString();
|
||||
res.confirm(usertext);
|
||||
}
|
||||
});
|
||||
dlg.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
res.cancel();
|
||||
}
|
||||
});
|
||||
dlg.create();
|
||||
dlg.show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle database quota exceeded notification.
|
||||
*
|
||||
* @param url
|
||||
* @param databaseIdentifier
|
||||
* @param currentQuota
|
||||
* @param estimatedSize
|
||||
* @param totalUsedQuota
|
||||
* @param quotaUpdater
|
||||
*/
|
||||
@Override
|
||||
public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
|
||||
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
|
||||
{
|
||||
LOG.d(TAG, "DroidGap: onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
|
||||
|
||||
if (estimatedSize < MAX_QUOTA)
|
||||
{
|
||||
//increase for 1Mb
|
||||
long newQuota = estimatedSize;
|
||||
LOG.d(TAG, "calling quotaUpdater.updateQuota newQuota: %d", newQuota);
|
||||
quotaUpdater.updateQuota(newQuota);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the quota to whatever it is and force an error
|
||||
// TODO: get docs on how to handle this properly
|
||||
quotaUpdater.updateQuota(currentQuota);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onConsoleMessage(String message, int lineNumber, String sourceID)
|
||||
{
|
||||
LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
|
||||
super.onConsoleMessage(message, lineNumber, sourceID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
|
||||
{
|
||||
if (consoleMessage.message() != null)
|
||||
LOG.d(TAG, consoleMessage.message());
|
||||
return super.onConsoleMessage(consoleMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
|
||||
*
|
||||
* @param origin
|
||||
* @param callback
|
||||
*/
|
||||
public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
|
||||
super.onGeolocationPermissionsShowPrompt(origin, callback);
|
||||
callback.invoke(origin, true, false);
|
||||
}
|
||||
}
|
||||
105
framework/src/org/apache/cordova/CordovaClientCertRequest.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.webkit.ClientCertRequest;
|
||||
|
||||
/**
|
||||
* Implementation of the ICordovaClientCertRequest for Android WebView.
|
||||
*
|
||||
*/
|
||||
public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
|
||||
private final ClientCertRequest request;
|
||||
|
||||
public CordovaClientCertRequest(ClientCertRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel this request
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void cancel()
|
||||
{
|
||||
request.cancel();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the host name of the server requesting the certificate.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public String getHost()
|
||||
{
|
||||
return request.getHost();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the acceptable types of asymmetric keys (can be null).
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public String[] getKeyTypes()
|
||||
{
|
||||
return request.getKeyTypes();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the port number of the server requesting the certificate.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public int getPort()
|
||||
{
|
||||
return request.getPort();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public Principal[] getPrincipals()
|
||||
{
|
||||
return request.getPrincipals();
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore the request for now. Do not remember user's choice.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void ignore()
|
||||
{
|
||||
request.ignore();
|
||||
}
|
||||
|
||||
/*
|
||||
* Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests.
|
||||
*
|
||||
* @param privateKey The privateKey
|
||||
* @param chain The certificate chain
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void proceed(PrivateKey privateKey, X509Certificate[] chain)
|
||||
{
|
||||
request.proceed(privateKey, chain);
|
||||
}
|
||||
}
|
||||
152
framework/src/org/apache/cordova/CordovaDialogsHelper.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.EditText;
|
||||
|
||||
/**
|
||||
* Helper class for WebViews to implement prompt(), alert(), confirm() dialogs.
|
||||
*/
|
||||
public class CordovaDialogsHelper {
|
||||
private final Context context;
|
||||
private AlertDialog lastHandledDialog;
|
||||
|
||||
public CordovaDialogsHelper(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void showAlert(String message, final Result result) {
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(context);
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle("Alert");
|
||||
//Don't let alerts break the back button
|
||||
dlg.setCancelable(true);
|
||||
dlg.setPositiveButton(android.R.string.ok,
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.gotResult(true, null);
|
||||
}
|
||||
});
|
||||
dlg.setOnCancelListener(
|
||||
new DialogInterface.OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
result.gotResult(false, null);
|
||||
}
|
||||
});
|
||||
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||
//DO NOTHING
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
result.gotResult(true, null);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
});
|
||||
lastHandledDialog = dlg.show();
|
||||
}
|
||||
|
||||
public void showConfirm(String message, final Result result) {
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(context);
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle("Confirm");
|
||||
dlg.setCancelable(true);
|
||||
dlg.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.gotResult(true, null);
|
||||
}
|
||||
});
|
||||
dlg.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.gotResult(false, null);
|
||||
}
|
||||
});
|
||||
dlg.setOnCancelListener(
|
||||
new DialogInterface.OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
result.gotResult(false, null);
|
||||
}
|
||||
});
|
||||
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||
//DO NOTHING
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
result.gotResult(false, null);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
});
|
||||
lastHandledDialog = dlg.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the client to display a prompt dialog to the user.
|
||||
* If the client returns true, WebView will assume that the client will
|
||||
* handle the prompt dialog and call the appropriate JsPromptResult method.
|
||||
*
|
||||
* Since we are hacking prompts for our own purposes, we should not be using them for
|
||||
* this purpose, perhaps we should hack console.log to do this instead!
|
||||
*/
|
||||
public void showPrompt(String message, String defaultValue, final Result result) {
|
||||
// Returning false would also show a dialog, but the default one shows the origin (ugly).
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(context);
|
||||
dlg.setMessage(message);
|
||||
final EditText input = new EditText(context);
|
||||
if (defaultValue != null) {
|
||||
input.setText(defaultValue);
|
||||
}
|
||||
dlg.setView(input);
|
||||
dlg.setCancelable(false);
|
||||
dlg.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
String userText = input.getText().toString();
|
||||
result.gotResult(true, userText);
|
||||
}
|
||||
});
|
||||
dlg.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
result.gotResult(false, null);
|
||||
}
|
||||
});
|
||||
lastHandledDialog = dlg.show();
|
||||
}
|
||||
|
||||
public void destroyLastDialog(){
|
||||
if (lastHandledDialog != null){
|
||||
lastHandledDialog.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public interface Result {
|
||||
public void gotResult(boolean success, String value);
|
||||
}
|
||||
}
|
||||
43
framework/src/org/apache/cordova/GPSListener.java → framework/src/org/apache/cordova/CordovaHttpAuthHandler.java
Executable file → Normal file
@@ -16,35 +16,36 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.location.LocationManager;
|
||||
import android.webkit.HttpAuthHandler;
|
||||
|
||||
/**
|
||||
* This class handles requests for GPS location services.
|
||||
*
|
||||
* Specifies interface for HTTP auth handler object which is used to handle auth requests and
|
||||
* specifying user credentials.
|
||||
*/
|
||||
public class GPSListener extends CordovaLocationListener {
|
||||
public GPSListener(LocationManager locationManager, GeoBroker m) {
|
||||
super(locationManager, m, "[Cordova GPSListener]");
|
||||
}
|
||||
public class CordovaHttpAuthHandler implements ICordovaHttpAuthHandler {
|
||||
|
||||
private final HttpAuthHandler handler;
|
||||
|
||||
public CordovaHttpAuthHandler(HttpAuthHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start requesting location updates.
|
||||
*
|
||||
* @param interval
|
||||
* Instructs the WebView to cancel the authentication request.
|
||||
*/
|
||||
@Override
|
||||
protected void start() {
|
||||
if (!this.running) {
|
||||
if (this.locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
|
||||
this.running = true;
|
||||
this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, this);
|
||||
} else {
|
||||
this.fail(CordovaLocationListener.POSITION_UNAVAILABLE, "GPS provider is not available.");
|
||||
}
|
||||
}
|
||||
public void cancel () {
|
||||
this.handler.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the WebView to proceed with the authentication with the given credentials.
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
*/
|
||||
public void proceed (String username, String password) {
|
||||
this.handler.proceed(username, password);
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,17 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova.api;
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* The Cordova activity abstract class that is extended by DroidGap.
|
||||
* The Activity interface that is implemented by CordovaActivity.
|
||||
* It is used to isolate plugin development, and remove dependency on entire Cordova library.
|
||||
*/
|
||||
public interface CordovaInterface {
|
||||
@@ -35,38 +39,30 @@ public interface CordovaInterface {
|
||||
* @param intent The intent to start
|
||||
* @param requestCode The request code that is passed to callback to identify the activity
|
||||
*/
|
||||
abstract public void startActivityForResult(IPlugin command, Intent intent, int requestCode);
|
||||
abstract public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode);
|
||||
|
||||
/**
|
||||
* Set the plugin to be called when a sub-activity exits.
|
||||
*
|
||||
* @param plugin The plugin on which onActivityResult is to be called
|
||||
*/
|
||||
abstract public void setActivityResultCallback(IPlugin plugin);
|
||||
|
||||
/**
|
||||
* Causes the Activity to override the back button behavior.
|
||||
*
|
||||
* @param override
|
||||
*/
|
||||
public abstract void bindBackButton(boolean override);
|
||||
|
||||
/**
|
||||
* A hook required to check if the Back Button is bound.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean isBackButtonBound();
|
||||
abstract public void setActivityResultCallback(CordovaPlugin plugin);
|
||||
|
||||
/**
|
||||
* Get the Android activity.
|
||||
*
|
||||
* @return
|
||||
* If a custom engine lives outside of the Activity's lifecycle the return value may be null.
|
||||
*
|
||||
* @return the Activity
|
||||
*/
|
||||
public abstract Activity getActivity();
|
||||
public abstract AppCompatActivity getActivity();
|
||||
|
||||
@Deprecated
|
||||
public abstract void cancelLoadUrl();
|
||||
/**
|
||||
* Get the Android context.
|
||||
*
|
||||
* @return the Context
|
||||
*/
|
||||
public Context getContext();
|
||||
|
||||
/**
|
||||
* Called when a message is sent to plugin.
|
||||
@@ -76,4 +72,25 @@ public interface CordovaInterface {
|
||||
* @return Object or null
|
||||
*/
|
||||
public Object onMessage(String id, Object data);
|
||||
|
||||
/**
|
||||
* Returns a shared thread pool that can be used for background tasks.
|
||||
*/
|
||||
public ExecutorService getThreadPool();
|
||||
|
||||
/**
|
||||
* Sends a permission request to the activity for one permission.
|
||||
*/
|
||||
public void requestPermission(CordovaPlugin plugin, int requestCode, String permission);
|
||||
|
||||
/**
|
||||
* Sends a permission request to the activity for a group of permissions
|
||||
*/
|
||||
public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions);
|
||||
|
||||
/**
|
||||
* Check for a permission. Returns true if the permission is granted, false otherwise.
|
||||
*/
|
||||
public boolean hasPermission(String permission);
|
||||
|
||||
}
|
||||
250
framework/src/org/apache/cordova/CordovaInterfaceImpl.java
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Default implementation of CordovaInterface.
|
||||
*/
|
||||
public class CordovaInterfaceImpl implements CordovaInterface {
|
||||
private static final String TAG = "CordovaInterfaceImpl";
|
||||
protected AppCompatActivity activity;
|
||||
protected ExecutorService threadPool;
|
||||
protected PluginManager pluginManager;
|
||||
|
||||
protected ActivityResultHolder savedResult;
|
||||
protected CallbackMap permissionResultCallbacks;
|
||||
protected CordovaPlugin activityResultCallback;
|
||||
protected String initCallbackService;
|
||||
protected int activityResultRequestCode;
|
||||
protected boolean activityWasDestroyed = false;
|
||||
protected Bundle savedPluginState;
|
||||
|
||||
public CordovaInterfaceImpl(AppCompatActivity activity) {
|
||||
this(activity, Executors.newCachedThreadPool());
|
||||
}
|
||||
|
||||
public CordovaInterfaceImpl(AppCompatActivity activity, ExecutorService threadPool) {
|
||||
this.activity = activity;
|
||||
this.threadPool = threadPool;
|
||||
this.permissionResultCallbacks = new CallbackMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
|
||||
setActivityResultCallback(command);
|
||||
try {
|
||||
activity.startActivityForResult(intent, requestCode);
|
||||
} catch (RuntimeException e) { // E.g.: ActivityNotFoundException
|
||||
activityResultCallback = null;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityResultCallback(CordovaPlugin plugin) {
|
||||
// Cancel any previously pending activity.
|
||||
if (activityResultCallback != null) {
|
||||
activityResultCallback.onActivityResult(activityResultRequestCode, AppCompatActivity.RESULT_CANCELED, null);
|
||||
}
|
||||
activityResultCallback = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onMessage(String id, Object data) {
|
||||
if ("exit".equals(id)) {
|
||||
activity.finish();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutorService getThreadPool() {
|
||||
return threadPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches any pending onActivityResult callbacks and sends the resume event if the
|
||||
* Activity was destroyed by the OS.
|
||||
*/
|
||||
public void onCordovaInit(PluginManager pluginManager) {
|
||||
this.pluginManager = pluginManager;
|
||||
if (savedResult != null) {
|
||||
onActivityResult(savedResult.requestCode, savedResult.resultCode, savedResult.intent);
|
||||
} else if(activityWasDestroyed) {
|
||||
// If there was no Activity result, we still need to send out the resume event if the
|
||||
// Activity was destroyed by the OS
|
||||
activityWasDestroyed = false;
|
||||
if(pluginManager != null)
|
||||
{
|
||||
CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
|
||||
if(appPlugin != null) {
|
||||
JSONObject obj = new JSONObject();
|
||||
try {
|
||||
obj.put("action", "resume");
|
||||
} catch (JSONException e) {
|
||||
LOG.e(TAG, "Failed to create event message", e);
|
||||
}
|
||||
appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, obj));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Routes the result to the awaiting plugin. Returns false if no plugin was waiting.
|
||||
*/
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
CordovaPlugin callback = activityResultCallback;
|
||||
if(callback == null && initCallbackService != null) {
|
||||
// The application was restarted, but had defined an initial callback
|
||||
// before being shut down.
|
||||
savedResult = new ActivityResultHolder(requestCode, resultCode, intent);
|
||||
if (pluginManager != null) {
|
||||
callback = pluginManager.getPlugin(initCallbackService);
|
||||
if(callback != null) {
|
||||
callback.onRestoreStateForActivityResult(savedPluginState.getBundle(callback.getServiceName()),
|
||||
new ResumeCallback(callback.getServiceName(), pluginManager));
|
||||
}
|
||||
}
|
||||
}
|
||||
activityResultCallback = null;
|
||||
|
||||
if (callback != null) {
|
||||
LOG.d(TAG, "Sending activity result to plugin");
|
||||
initCallbackService = null;
|
||||
savedResult = null;
|
||||
callback.onActivityResult(requestCode, resultCode, intent);
|
||||
return true;
|
||||
}
|
||||
LOG.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : "."));
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this from your startActivityForResult() overload. This is required to catch the case
|
||||
* where plugins use Activity.startActivityForResult() + CordovaInterface.setActivityResultCallback()
|
||||
* rather than CordovaInterface.startActivityForResult().
|
||||
*/
|
||||
public void setActivityResultRequestCode(int requestCode) {
|
||||
activityResultRequestCode = requestCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves parameters for startActivityForResult().
|
||||
*/
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
if (activityResultCallback != null) {
|
||||
String serviceName = activityResultCallback.getServiceName();
|
||||
outState.putString("callbackService", serviceName);
|
||||
}
|
||||
if(pluginManager != null){
|
||||
outState.putBundle("plugin", pluginManager.onSaveInstanceState());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this from onCreate() so that any saved startActivityForResult parameters will be restored.
|
||||
*/
|
||||
public void restoreInstanceState(Bundle savedInstanceState) {
|
||||
initCallbackService = savedInstanceState.getString("callbackService");
|
||||
savedPluginState = savedInstanceState.getBundle("plugin");
|
||||
activityWasDestroyed = true;
|
||||
}
|
||||
|
||||
private static class ActivityResultHolder {
|
||||
private int requestCode;
|
||||
private int resultCode;
|
||||
private Intent intent;
|
||||
|
||||
public ActivityResultHolder(int requestCode, int resultCode, Intent intent) {
|
||||
this.requestCode = requestCode;
|
||||
this.resultCode = resultCode;
|
||||
this.intent = intent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when the user grants permissions
|
||||
*
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
public void onRequestPermissionResult(int requestCode, String[] permissions,
|
||||
int[] grantResults) throws JSONException {
|
||||
Pair<CordovaPlugin, Integer> callback = permissionResultCallbacks.getAndRemoveCallback(requestCode);
|
||||
if(callback != null) {
|
||||
callback.first.onRequestPermissionResult(callback.second, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
|
||||
String[] permissions = new String [1];
|
||||
permissions[0] = permission;
|
||||
requestPermissions(plugin, requestCode, permissions);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) {
|
||||
int mappedRequestCode = permissionResultCallbacks.registerCallback(plugin, requestCode);
|
||||
getActivity().requestPermissions(permissions, mappedRequestCode);
|
||||
}
|
||||
|
||||
public boolean hasPermission(String permission)
|
||||
{
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
{
|
||||
int result = activity.checkSelfPermission(permission);
|
||||
return PackageManager.PERMISSION_GRANTED == result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class CordovaLocationListener implements LocationListener {
|
||||
public static int PERMISSION_DENIED = 1;
|
||||
public static int POSITION_UNAVAILABLE = 2;
|
||||
public static int TIMEOUT = 3;
|
||||
|
||||
protected LocationManager locationManager;
|
||||
private GeoBroker owner;
|
||||
protected boolean running = false;
|
||||
|
||||
public HashMap<String, String> watches = new HashMap<String, String>();
|
||||
private List<String> callbacks = new ArrayList<String>();
|
||||
|
||||
private String TAG = "[Cordova Location Listener]";
|
||||
|
||||
public CordovaLocationListener(LocationManager manager, GeoBroker broker, String tag) {
|
||||
this.locationManager = manager;
|
||||
this.owner = broker;
|
||||
this.TAG = tag;
|
||||
}
|
||||
|
||||
protected void fail(int code, String message) {
|
||||
for (String callbackId: this.callbacks)
|
||||
{
|
||||
this.owner.fail(code, message, callbackId);
|
||||
}
|
||||
this.callbacks.clear();
|
||||
|
||||
Iterator it = this.watches.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry pairs = (Map.Entry)it.next();
|
||||
this.owner.fail(code, message, (String)pairs.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void win(Location loc) {
|
||||
for (String callbackId: this.callbacks)
|
||||
{
|
||||
this.owner.win(loc, callbackId);
|
||||
}
|
||||
this.callbacks.clear();
|
||||
|
||||
Iterator it = this.watches.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry pairs = (Map.Entry)it.next();
|
||||
this.owner.win(loc, (String)pairs.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Location Listener Methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called when the provider is disabled by the user.
|
||||
*
|
||||
* @param provider
|
||||
*/
|
||||
public void onProviderDisabled(String provider) {
|
||||
Log.d(TAG, "Location provider '" + provider + "' disabled.");
|
||||
this.fail(POSITION_UNAVAILABLE, "GPS provider disabled.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the provider is enabled by the user.
|
||||
*
|
||||
* @param provider
|
||||
*/
|
||||
public void onProviderEnabled(String provider) {
|
||||
Log.d(TAG, "Location provider "+ provider + " has been enabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the provider status changes. This method is called when a
|
||||
* provider is unable to fetch a location or if the provider has recently
|
||||
* become available after a period of unavailability.
|
||||
*
|
||||
* @param provider
|
||||
* @param status
|
||||
* @param extras
|
||||
*/
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
Log.d(TAG, "The status of the provider " + provider + " has changed");
|
||||
if (status == 0) {
|
||||
Log.d(TAG, provider + " is OUT OF SERVICE");
|
||||
this.fail(CordovaLocationListener.POSITION_UNAVAILABLE, "Provider " + provider + " is out of service.");
|
||||
}
|
||||
else if (status == 1) {
|
||||
Log.d(TAG, provider + " is TEMPORARILY_UNAVAILABLE");
|
||||
}
|
||||
else {
|
||||
Log.d(TAG, provider + " is AVAILABLE");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the location has changed.
|
||||
*
|
||||
* @param location
|
||||
*/
|
||||
public void onLocationChanged(Location location) {
|
||||
Log.d(TAG, "The location has been updated!");
|
||||
this.win(location);
|
||||
}
|
||||
|
||||
// PUBLIC
|
||||
|
||||
public int size() {
|
||||
return this.watches.size() + this.callbacks.size();
|
||||
}
|
||||
|
||||
public void addWatch(String timerId, String callbackId) {
|
||||
this.watches.put(timerId, callbackId);
|
||||
if (this.size() == 1) {
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
public void addCallback(String callbackId) {
|
||||
this.callbacks.add(callbackId);
|
||||
if (this.size() == 1) {
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
public void clearWatch(String timerId) {
|
||||
if (this.watches.containsKey(timerId)) {
|
||||
this.watches.remove(timerId);
|
||||
}
|
||||
if (this.size() == 0) {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy listener.
|
||||
*/
|
||||
public void destroy() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
// LOCAL
|
||||
|
||||
/**
|
||||
* Start requesting location updates.
|
||||
*
|
||||
* @param interval
|
||||
*/
|
||||
protected void start() {
|
||||
if (!this.running) {
|
||||
if (this.locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
|
||||
this.running = true;
|
||||
this.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 10, this);
|
||||
} else {
|
||||
this.fail(CordovaLocationListener.POSITION_UNAVAILABLE, "Network provider is not available.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop receiving location updates.
|
||||
*/
|
||||
private void stop() {
|
||||
if (this.running) {
|
||||
this.locationManager.removeUpdates(this);
|
||||
this.running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
445
framework/src/org/apache/cordova/CordovaPlugin.java
Normal file
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import org.apache.cordova.CordovaArgs;
|
||||
import org.apache.cordova.CordovaWebView;
|
||||
import org.apache.cordova.CordovaInterface;
|
||||
import org.apache.cordova.CallbackContext;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Plugins must extend this class and override one of the execute methods.
|
||||
*/
|
||||
public class CordovaPlugin {
|
||||
public CordovaWebView webView;
|
||||
public CordovaInterface cordova;
|
||||
protected CordovaPreferences preferences;
|
||||
private String serviceName;
|
||||
|
||||
/**
|
||||
* Call this after constructing to initialize the plugin.
|
||||
* Final because we want to be able to change args without breaking plugins.
|
||||
*/
|
||||
public final void privateInitialize(String serviceName, CordovaInterface cordova, CordovaWebView webView, CordovaPreferences preferences) {
|
||||
assert this.cordova == null;
|
||||
this.serviceName = serviceName;
|
||||
this.cordova = cordova;
|
||||
this.webView = webView;
|
||||
this.preferences = preferences;
|
||||
initialize(cordova, webView);
|
||||
pluginInitialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after plugin construction and fields have been initialized.
|
||||
* Prefer to use pluginInitialize instead since there is no value in
|
||||
* having parameters on the initialize() function.
|
||||
*/
|
||||
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after plugin construction and fields have been initialized.
|
||||
*/
|
||||
protected void pluginInitialize() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin's service name (what you'd use when calling pluginManger.getPlugin())
|
||||
*/
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request.
|
||||
*
|
||||
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
|
||||
* cordova.getThreadPool().execute(runnable);
|
||||
*
|
||||
* To run on the UI thread, use:
|
||||
* cordova.getActivity().runOnUiThread(runnable);
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param rawArgs The exec() arguments in JSON form.
|
||||
* @param callbackContext The callback context used when calling back into JavaScript.
|
||||
* @return Whether the action was valid.
|
||||
*/
|
||||
public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
|
||||
JSONArray args = new JSONArray(rawArgs);
|
||||
return execute(action, args, callbackContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request.
|
||||
*
|
||||
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
|
||||
* cordova.getThreadPool().execute(runnable);
|
||||
*
|
||||
* To run on the UI thread, use:
|
||||
* cordova.getActivity().runOnUiThread(runnable);
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args The exec() arguments.
|
||||
* @param callbackContext The callback context used when calling back into JavaScript.
|
||||
* @return Whether the action was valid.
|
||||
*/
|
||||
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
|
||||
CordovaArgs cordovaArgs = new CordovaArgs(args);
|
||||
return execute(action, cordovaArgs, callbackContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the request.
|
||||
*
|
||||
* This method is called from the WebView thread. To do a non-trivial amount of work, use:
|
||||
* cordova.getThreadPool().execute(runnable);
|
||||
*
|
||||
* To run on the UI thread, use:
|
||||
* cordova.getActivity().runOnUiThread(runnable);
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args The exec() arguments, wrapped with some Cordova helpers.
|
||||
* @param callbackContext The callback context used when calling back into JavaScript.
|
||||
* @return Whether the action was valid.
|
||||
*/
|
||||
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the system is about to start resuming a previous activity.
|
||||
*
|
||||
* @param multitasking Flag indicating if multitasking is turned on for app
|
||||
*/
|
||||
public void onPause(boolean multitasking) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity will start interacting with the user.
|
||||
*
|
||||
* @param multitasking Flag indicating if multitasking is turned on for app
|
||||
*/
|
||||
public void onResume(boolean multitasking) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is becoming visible to the user.
|
||||
*/
|
||||
public void onStart() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is no longer visible to the user.
|
||||
*/
|
||||
public void onStop() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity receives a new intent.
|
||||
*/
|
||||
public void onNewIntent(Intent intent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The final call you receive before your activity is destroyed.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Activity is being destroyed (e.g. if a plugin calls out to an external
|
||||
* Activity and the OS kills the CordovaActivity in the background). The plugin should save its
|
||||
* state in this method only if it is awaiting the result of an external Activity and needs
|
||||
* to preserve some information so as to handle that result; onRestoreStateForActivityResult()
|
||||
* will only be called if the plugin is the recipient of an Activity result
|
||||
*
|
||||
* @return Bundle containing the state of the plugin or null if state does not need to be saved
|
||||
*/
|
||||
public Bundle onSaveInstanceState() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a plugin is the recipient of an Activity result after the CordovaActivity has
|
||||
* been destroyed. The Bundle will be the same as the one the plugin returned in
|
||||
* onSaveInstanceState()
|
||||
*
|
||||
* @param state Bundle containing the state of the plugin
|
||||
* @param callbackContext Replacement Context to return the plugin result to
|
||||
*/
|
||||
public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {}
|
||||
|
||||
/**
|
||||
* Called when a message is sent to plugin.
|
||||
*
|
||||
* @param id The message id
|
||||
* @param data The message data
|
||||
* @return Object to stop propagation or null
|
||||
*/
|
||||
public Object onMessage(String id, Object data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an activity you launched exits, giving you the requestCode you started it with,
|
||||
* the resultCode it returned, and any additional data from it.
|
||||
*
|
||||
* @param requestCode The request code originally supplied to startActivityForResult(),
|
||||
* allowing you to identify who this result came from.
|
||||
* @param resultCode The integer result code returned by the child activity through its setResult().
|
||||
* @param intent An Intent, which can return result data to the caller (various data can be
|
||||
* attached to Intent "extras").
|
||||
*/
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for blocking the loading of external resources.
|
||||
*
|
||||
* This will be called when the WebView's shouldInterceptRequest wants to
|
||||
* know whether to open a connection to an external resource. Return false
|
||||
* to block the request: if any plugin returns false, Cordova will block
|
||||
* the request. If all plugins return null, the default policy will be
|
||||
* enforced. If at least one plugin returns true, and no plugins return
|
||||
* false, then the request will proceed.
|
||||
*
|
||||
* Note that this only affects resource requests which are routed through
|
||||
* WebViewClient.shouldInterceptRequest, such as XMLHttpRequest requests and
|
||||
* img tag loads. WebSockets and media requests (such as <video> and <audio>
|
||||
* tags) are not affected by this method. Use CSP headers to control access
|
||||
* to such resources.
|
||||
*/
|
||||
public Boolean shouldAllowRequest(String url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for blocking navigation by the Cordova WebView. This applies both to top-level and
|
||||
* iframe navigations.
|
||||
*
|
||||
* This will be called when the WebView's needs to know whether to navigate
|
||||
* to a new page. Return false to block the navigation: if any plugin
|
||||
* returns false, Cordova will block the navigation. If all plugins return
|
||||
* null, the default policy will be enforced. It at least one plugin returns
|
||||
* true, and no plugins return false, then the navigation will proceed.
|
||||
*/
|
||||
public Boolean shouldAllowNavigation(String url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for allowing page to call exec(). By default, this returns the result of
|
||||
* shouldAllowNavigation(). It's generally unsafe to allow untrusted content to be loaded
|
||||
* into a CordovaWebView, even within an iframe, so it's best not to touch this.
|
||||
*/
|
||||
public Boolean shouldAllowBridgeAccess(String url) {
|
||||
return shouldAllowNavigation(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for blocking the launching of Intents by the Cordova application.
|
||||
*
|
||||
* This will be called when the WebView will not navigate to a page, but
|
||||
* could launch an intent to handle the URL. Return false to block this: if
|
||||
* any plugin returns false, Cordova will block the navigation. If all
|
||||
* plugins return null, the default policy will be enforced. If at least one
|
||||
* plugin returns true, and no plugins return false, then the URL will be
|
||||
* opened.
|
||||
*/
|
||||
public Boolean shouldOpenExternalUrl(String url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to handle a link being clicked. Return true here to cancel the navigation.
|
||||
*
|
||||
* @param url The URL that is trying to be loaded in the Cordova webview.
|
||||
* @return Return true to prevent the URL from loading. Default is false.
|
||||
*/
|
||||
public boolean onOverrideUrlLoading(String url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for redirecting requests. Applies to WebView requests as well as requests made by plugins.
|
||||
* To handle the request directly, return a URI in the form:
|
||||
*
|
||||
* cdvplugin://pluginId/...
|
||||
*
|
||||
* And implement handleOpenForRead().
|
||||
* To make this easier, use the toPluginUri() and fromPluginUri() helpers:
|
||||
*
|
||||
* public Uri remapUri(Uri uri) { return toPluginUri(uri); }
|
||||
*
|
||||
* public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
|
||||
* Uri origUri = fromPluginUri(uri);
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
public Uri remapUri(Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to handle CordovaResourceApi.openForRead() calls for a cdvplugin://pluginId/ URL.
|
||||
* Should never return null.
|
||||
* Added in cordova-android@4.0.0
|
||||
*/
|
||||
public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
|
||||
throw new FileNotFoundException("Plugin can't handle uri: " + uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refer to remapUri()
|
||||
* Added in cordova-android@4.0.0
|
||||
*/
|
||||
protected Uri toPluginUri(Uri origUri) {
|
||||
return new Uri.Builder()
|
||||
.scheme(CordovaResourceApi.PLUGIN_URI_SCHEME)
|
||||
.authority(serviceName)
|
||||
.appendQueryParameter("origUri", origUri.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refer to remapUri()
|
||||
* Added in cordova-android@4.0.0
|
||||
*/
|
||||
protected Uri fromPluginUri(Uri pluginUri) {
|
||||
return Uri.parse(pluginUri.getQueryParameter("origUri"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the WebView does a top-level navigation or refreshes.
|
||||
*
|
||||
* Plugins should stop any long-running processes and clean up internal state.
|
||||
*
|
||||
* Does nothing by default.
|
||||
*/
|
||||
public void onReset() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the system received an HTTP authentication request. Plugin can use
|
||||
* the supplied HttpAuthHandler to process this auth challenge.
|
||||
*
|
||||
* @param view The WebView that is initiating the callback
|
||||
* @param handler The HttpAuthHandler used to set the WebView's response
|
||||
* @param host The host requiring authentication
|
||||
* @param realm The realm for which authentication is required
|
||||
*
|
||||
* @return Returns True if plugin will resolve this auth challenge, otherwise False
|
||||
*
|
||||
*/
|
||||
public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when he system received an SSL client certificate request. Plugin can use
|
||||
* the supplied ClientCertRequest to process this certificate challenge.
|
||||
*
|
||||
* @param view The WebView that is initiating the callback
|
||||
* @param request The client certificate request
|
||||
*
|
||||
* @return Returns True if plugin will resolve this auth challenge, otherwise False
|
||||
*
|
||||
*/
|
||||
public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when the device configuration changes while your activity is running.
|
||||
*
|
||||
* @param newConfig The new device configuration
|
||||
*/
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the Plugin Manager when we need to actually request permissions
|
||||
*
|
||||
* @param requestCode Passed to the activity to track the request
|
||||
*
|
||||
* @return Returns the permission that was stored in the plugin
|
||||
*/
|
||||
|
||||
public void requestPermissions(int requestCode) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the WebView implementation to check for geolocation permissions, can be used
|
||||
* by other Java methods in the event that a plugin is using this as a dependency.
|
||||
*
|
||||
* @return Returns true if the plugin has all the permissions it needs to operate.
|
||||
*/
|
||||
|
||||
public boolean hasPermisssion() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when the user grants permissions
|
||||
*
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*
|
||||
* @deprecated Use {@link #onRequestPermissionsResult} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onRequestPermissionResult(int requestCode, String[] permissions,
|
||||
int[] grantResults) throws JSONException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system when the user grants permissions
|
||||
*
|
||||
* @param requestCode
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
int[] grantResults) throws JSONException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow plugins to supply a PathHandler for the WebViewAssetHandler
|
||||
* @return a CordovaPluginPathHandler which listen for paths and returns a response
|
||||
*/
|
||||
public CordovaPluginPathHandler getPathHandler() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import androidx.webkit.WebViewAssetLoader;
|
||||
|
||||
/**
|
||||
* Wrapper class for path and handler
|
||||
*/
|
||||
public class CordovaPluginPathHandler {
|
||||
|
||||
private final WebViewAssetLoader.PathHandler handler;
|
||||
|
||||
public CordovaPluginPathHandler(WebViewAssetLoader.PathHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public WebViewAssetLoader.PathHandler getPathHandler() {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
101
framework/src/org/apache/cordova/CordovaPreferences.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cordova.LOG;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class CordovaPreferences {
|
||||
private HashMap<String, String> prefs = new HashMap<String, String>(20);
|
||||
private Bundle preferencesBundleExtras;
|
||||
|
||||
public void setPreferencesBundle(Bundle extras) {
|
||||
preferencesBundleExtras = extras;
|
||||
}
|
||||
|
||||
public void set(String name, String value) {
|
||||
prefs.put(name.toLowerCase(Locale.ENGLISH), value);
|
||||
}
|
||||
|
||||
public void set(String name, boolean value) {
|
||||
set(name, "" + value);
|
||||
}
|
||||
|
||||
public void set(String name, int value) {
|
||||
set(name, "" + value);
|
||||
}
|
||||
|
||||
public void set(String name, double value) {
|
||||
set(name, "" + value);
|
||||
}
|
||||
|
||||
public Map<String, String> getAll() {
|
||||
return prefs;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String name, boolean defaultValue) {
|
||||
name = name.toLowerCase(Locale.ENGLISH);
|
||||
String value = prefs.get(name);
|
||||
if (value != null) {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Added in 4.0.0
|
||||
public boolean contains(String name) {
|
||||
return getString(name, null) != null;
|
||||
}
|
||||
|
||||
public int getInteger(String name, int defaultValue) {
|
||||
name = name.toLowerCase(Locale.ENGLISH);
|
||||
String value = prefs.get(name);
|
||||
if (value != null) {
|
||||
// Use Integer.decode() can't handle it if the highest bit is set.
|
||||
return (int)(long)Long.decode(value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public double getDouble(String name, double defaultValue) {
|
||||
name = name.toLowerCase(Locale.ENGLISH);
|
||||
String value = prefs.get(name);
|
||||
if (value != null) {
|
||||
return Double.valueOf(value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public String getString(String name, String defaultValue) {
|
||||
name = name.toLowerCase(Locale.ENGLISH);
|
||||
String value = prefs.get(name);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
479
framework/src/org/apache/cordova/CordovaResourceApi.java
Normal file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.AssetManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Looper;
|
||||
import android.util.Base64;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* What this class provides:
|
||||
* 1. Helpers for reading & writing to URLs.
|
||||
* - E.g. handles assets, resources, content providers, files, data URIs, http[s]
|
||||
* - E.g. Can be used to query for mime-type & content length.
|
||||
*
|
||||
* 2. To allow plugins to redirect URLs (via remapUrl).
|
||||
* - All plugins should call remapUrl() on URLs they receive from JS *before*
|
||||
* passing the URL onto other utility functions in this class.
|
||||
* - For an example usage of this, refer to the org.apache.cordova.file plugin.
|
||||
*
|
||||
* Future Work:
|
||||
* - Consider using a Cursor to query content URLs for their size (like the file plugin does).
|
||||
* - Allow plugins to remapUri to "cdv-plugin://plugin-name/foo", which CordovaResourceApi
|
||||
* would then delegate to pluginManager.getPlugin(plugin-name).openForRead(url)
|
||||
* - Currently, plugins *can* do this by remapping to a data: URL, but it's inefficient
|
||||
* for large payloads.
|
||||
*/
|
||||
public class CordovaResourceApi {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String LOG_TAG = "CordovaResourceApi";
|
||||
|
||||
public static final int URI_TYPE_FILE = 0;
|
||||
public static final int URI_TYPE_ASSET = 1;
|
||||
public static final int URI_TYPE_CONTENT = 2;
|
||||
public static final int URI_TYPE_RESOURCE = 3;
|
||||
public static final int URI_TYPE_DATA = 4;
|
||||
public static final int URI_TYPE_HTTP = 5;
|
||||
public static final int URI_TYPE_HTTPS = 6;
|
||||
public static final int URI_TYPE_PLUGIN = 7;
|
||||
public static final int URI_TYPE_UNKNOWN = -1;
|
||||
|
||||
public static final String PLUGIN_URI_SCHEME = "cdvplugin";
|
||||
|
||||
private static final String[] LOCAL_FILE_PROJECTION = { "_data" };
|
||||
|
||||
public static Thread jsThread;
|
||||
|
||||
private final AssetManager assetManager;
|
||||
private final ContentResolver contentResolver;
|
||||
private final PluginManager pluginManager;
|
||||
private boolean threadCheckingEnabled = true;
|
||||
|
||||
|
||||
public CordovaResourceApi(Context context, PluginManager pluginManager) {
|
||||
this.contentResolver = context.getContentResolver();
|
||||
this.assetManager = context.getAssets();
|
||||
this.pluginManager = pluginManager;
|
||||
}
|
||||
|
||||
public void setThreadCheckingEnabled(boolean value) {
|
||||
threadCheckingEnabled = value;
|
||||
}
|
||||
|
||||
public boolean isThreadCheckingEnabled() {
|
||||
return threadCheckingEnabled;
|
||||
}
|
||||
|
||||
|
||||
public static int getUriType(Uri uri) {
|
||||
assertNonRelative(uri);
|
||||
String scheme = uri.getScheme();
|
||||
if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(scheme)) {
|
||||
return URI_TYPE_CONTENT;
|
||||
}
|
||||
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equalsIgnoreCase(scheme)) {
|
||||
return URI_TYPE_RESOURCE;
|
||||
}
|
||||
if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(scheme)) {
|
||||
if (uri.getPath().startsWith("/android_asset/")) {
|
||||
return URI_TYPE_ASSET;
|
||||
}
|
||||
return URI_TYPE_FILE;
|
||||
}
|
||||
if ("data".equalsIgnoreCase(scheme)) {
|
||||
return URI_TYPE_DATA;
|
||||
}
|
||||
if ("http".equalsIgnoreCase(scheme)) {
|
||||
return URI_TYPE_HTTP;
|
||||
}
|
||||
if ("https".equalsIgnoreCase(scheme)) {
|
||||
return URI_TYPE_HTTPS;
|
||||
}
|
||||
if (PLUGIN_URI_SCHEME.equalsIgnoreCase(scheme)) {
|
||||
return URI_TYPE_PLUGIN;
|
||||
}
|
||||
return URI_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public Uri remapUri(Uri uri) {
|
||||
assertNonRelative(uri);
|
||||
Uri pluginUri = pluginManager.remapUri(uri);
|
||||
return pluginUri != null ? pluginUri : uri;
|
||||
}
|
||||
|
||||
public String remapPath(String path) {
|
||||
return remapUri(Uri.fromFile(new File(path))).getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a File that points to the resource, or null if the resource
|
||||
* is not on the local filesystem.
|
||||
*/
|
||||
public File mapUriToFile(Uri uri) {
|
||||
assertBackgroundThread();
|
||||
switch (getUriType(uri)) {
|
||||
case URI_TYPE_FILE:
|
||||
return new File(uri.getPath());
|
||||
case URI_TYPE_CONTENT: {
|
||||
Cursor cursor = contentResolver.query(uri, LOCAL_FILE_PROJECTION, null, null, null);
|
||||
if (cursor != null) {
|
||||
try {
|
||||
int columnIndex = cursor.getColumnIndex(LOCAL_FILE_PROJECTION[0]);
|
||||
if (columnIndex != -1 && cursor.getCount() > 0) {
|
||||
cursor.moveToFirst();
|
||||
String realPath = cursor.getString(columnIndex);
|
||||
if (realPath != null) {
|
||||
return new File(realPath);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMimeType(Uri uri) {
|
||||
switch (getUriType(uri)) {
|
||||
case URI_TYPE_FILE:
|
||||
case URI_TYPE_ASSET:
|
||||
return getMimeTypeFromPath(uri.getPath());
|
||||
case URI_TYPE_CONTENT:
|
||||
case URI_TYPE_RESOURCE:
|
||||
return contentResolver.getType(uri);
|
||||
case URI_TYPE_DATA: {
|
||||
return getDataUriMimeType(uri);
|
||||
}
|
||||
case URI_TYPE_HTTP:
|
||||
case URI_TYPE_HTTPS: {
|
||||
try {
|
||||
HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
|
||||
conn.setDoInput(false);
|
||||
conn.setRequestMethod("HEAD");
|
||||
String mimeType = conn.getHeaderField("Content-Type");
|
||||
if (mimeType != null) {
|
||||
mimeType = mimeType.split(";")[0];
|
||||
}
|
||||
return mimeType;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
//This already exists
|
||||
private String getMimeTypeFromPath(String path) {
|
||||
String extension = path;
|
||||
int lastDot = extension.lastIndexOf('.');
|
||||
if (lastDot != -1) {
|
||||
extension = extension.substring(lastDot + 1);
|
||||
}
|
||||
// Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
|
||||
extension = extension.toLowerCase(Locale.getDefault());
|
||||
if (extension.equals("3ga")) {
|
||||
return "audio/3gpp";
|
||||
} else if (extension.equals("js")) {
|
||||
// Missing from the map :(.
|
||||
return "text/javascript";
|
||||
}
|
||||
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a stream to the given URI, also providing the MIME type & length.
|
||||
* @return Never returns null.
|
||||
* @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
|
||||
* resolved before being passed into this function.
|
||||
* @throws Throws an IOException if the URI cannot be opened.
|
||||
* @throws Throws an IllegalStateException if called on a foreground thread.
|
||||
*/
|
||||
public OpenForReadResult openForRead(Uri uri) throws IOException {
|
||||
return openForRead(uri, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a stream to the given URI, also providing the MIME type & length.
|
||||
* @return Never returns null.
|
||||
* @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
|
||||
* resolved before being passed into this function.
|
||||
* @throws Throws an IOException if the URI cannot be opened.
|
||||
* @throws Throws an IllegalStateException if called on a foreground thread and skipThreadCheck is false.
|
||||
*/
|
||||
public OpenForReadResult openForRead(Uri uri, boolean skipThreadCheck) throws IOException {
|
||||
if (!skipThreadCheck) {
|
||||
assertBackgroundThread();
|
||||
}
|
||||
switch (getUriType(uri)) {
|
||||
case URI_TYPE_FILE: {
|
||||
FileInputStream inputStream = new FileInputStream(uri.getPath());
|
||||
String mimeType = getMimeTypeFromPath(uri.getPath());
|
||||
long length = inputStream.getChannel().size();
|
||||
return new OpenForReadResult(uri, inputStream, mimeType, length, null);
|
||||
}
|
||||
case URI_TYPE_ASSET: {
|
||||
String assetPath = uri.getPath().substring(15);
|
||||
AssetFileDescriptor assetFd = null;
|
||||
InputStream inputStream;
|
||||
long length = -1;
|
||||
try {
|
||||
assetFd = assetManager.openFd(assetPath);
|
||||
inputStream = assetFd.createInputStream();
|
||||
length = assetFd.getLength();
|
||||
} catch (FileNotFoundException e) {
|
||||
// Will occur if the file is compressed.
|
||||
inputStream = assetManager.open(assetPath);
|
||||
length = inputStream.available();
|
||||
}
|
||||
String mimeType = getMimeTypeFromPath(assetPath);
|
||||
return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
|
||||
}
|
||||
case URI_TYPE_CONTENT:
|
||||
case URI_TYPE_RESOURCE: {
|
||||
String mimeType = contentResolver.getType(uri);
|
||||
AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, "r");
|
||||
InputStream inputStream = assetFd.createInputStream();
|
||||
long length = assetFd.getLength();
|
||||
return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
|
||||
}
|
||||
case URI_TYPE_DATA: {
|
||||
OpenForReadResult ret = readDataUri(uri);
|
||||
if (ret == null) {
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case URI_TYPE_HTTP:
|
||||
case URI_TYPE_HTTPS: {
|
||||
HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
|
||||
conn.setRequestProperty("Accept-Encoding", "gzip");
|
||||
conn.setDoInput(true);
|
||||
String mimeType = conn.getHeaderField("Content-Type");
|
||||
if (mimeType != null) {
|
||||
mimeType = mimeType.split(";")[0];
|
||||
}
|
||||
int length = conn.getContentLength();
|
||||
InputStream inputStream;
|
||||
if ("gzip".equals(conn.getContentEncoding())) {
|
||||
inputStream = new GZIPInputStream(conn.getInputStream());
|
||||
} else {
|
||||
inputStream = conn.getInputStream();
|
||||
}
|
||||
return new OpenForReadResult(uri, inputStream, mimeType, length, null);
|
||||
}
|
||||
case URI_TYPE_PLUGIN: {
|
||||
String pluginId = uri.getHost();
|
||||
CordovaPlugin plugin = pluginManager.getPlugin(pluginId);
|
||||
if (plugin == null) {
|
||||
throw new FileNotFoundException("Invalid plugin ID in URI: " + uri);
|
||||
}
|
||||
return plugin.handleOpenForRead(uri);
|
||||
}
|
||||
}
|
||||
throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
|
||||
}
|
||||
|
||||
public OutputStream openOutputStream(Uri uri) throws IOException {
|
||||
return openOutputStream(uri, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a stream to the given URI.
|
||||
* @return Never returns null.
|
||||
* @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
|
||||
* resolved before being passed into this function.
|
||||
* @throws Throws an IOException if the URI cannot be opened.
|
||||
*/
|
||||
public OutputStream openOutputStream(Uri uri, boolean append) throws IOException {
|
||||
assertBackgroundThread();
|
||||
switch (getUriType(uri)) {
|
||||
case URI_TYPE_FILE: {
|
||||
File localFile = new File(uri.getPath());
|
||||
File parent = localFile.getParentFile();
|
||||
if (parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
return new FileOutputStream(localFile, append);
|
||||
}
|
||||
case URI_TYPE_CONTENT:
|
||||
case URI_TYPE_RESOURCE: {
|
||||
AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, append ? "wa" : "w");
|
||||
return assetFd.createOutputStream();
|
||||
}
|
||||
}
|
||||
throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
|
||||
}
|
||||
|
||||
public HttpURLConnection createHttpConnection(Uri uri) throws IOException {
|
||||
assertBackgroundThread();
|
||||
return (HttpURLConnection)new URL(uri.toString()).openConnection();
|
||||
}
|
||||
|
||||
// Copies the input to the output in the most efficient manner possible.
|
||||
// Closes both streams.
|
||||
public void copyResource(OpenForReadResult input, OutputStream outputStream) throws IOException {
|
||||
assertBackgroundThread();
|
||||
try {
|
||||
InputStream inputStream = input.inputStream;
|
||||
if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
|
||||
FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
|
||||
FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
|
||||
long offset = 0;
|
||||
long length = input.length;
|
||||
if (input.assetFd != null) {
|
||||
offset = input.assetFd.getStartOffset();
|
||||
}
|
||||
// transferFrom()'s 2nd arg is a relative position. Need to set the absolute
|
||||
// position first.
|
||||
inChannel.position(offset);
|
||||
outChannel.transferFrom(inChannel, 0, length);
|
||||
} else {
|
||||
final int BUFFER_SIZE = 8192;
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
for (;;) {
|
||||
int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
|
||||
|
||||
if (bytesRead <= 0) {
|
||||
break;
|
||||
}
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
input.inputStream.close();
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void copyResource(Uri sourceUri, OutputStream outputStream) throws IOException {
|
||||
copyResource(openForRead(sourceUri), outputStream);
|
||||
}
|
||||
|
||||
// Added in 3.5.0.
|
||||
public void copyResource(Uri sourceUri, Uri dstUri) throws IOException {
|
||||
copyResource(openForRead(sourceUri), openOutputStream(dstUri));
|
||||
}
|
||||
|
||||
private void assertBackgroundThread() {
|
||||
if (threadCheckingEnabled) {
|
||||
Thread curThread = Thread.currentThread();
|
||||
if (curThread == Looper.getMainLooper().getThread()) {
|
||||
throw new IllegalStateException("Do not perform IO operations on the UI thread. Use CordovaInterface.getThreadPool() instead.");
|
||||
}
|
||||
if (curThread == jsThread) {
|
||||
throw new IllegalStateException("Tried to perform an IO operation on the WebCore thread. Use CordovaInterface.getThreadPool() instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getDataUriMimeType(Uri uri) {
|
||||
String uriAsString = uri.getSchemeSpecificPart();
|
||||
int commaPos = uriAsString.indexOf(',');
|
||||
if (commaPos == -1) {
|
||||
return null;
|
||||
}
|
||||
String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
|
||||
if (mimeParts.length > 0) {
|
||||
return mimeParts[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private OpenForReadResult readDataUri(Uri uri) {
|
||||
String uriAsString = uri.getSchemeSpecificPart();
|
||||
int commaPos = uriAsString.indexOf(',');
|
||||
if (commaPos == -1) {
|
||||
return null;
|
||||
}
|
||||
String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
|
||||
String contentType = null;
|
||||
boolean base64 = false;
|
||||
if (mimeParts.length > 0) {
|
||||
contentType = mimeParts[0];
|
||||
}
|
||||
for (int i = 1; i < mimeParts.length; ++i) {
|
||||
if ("base64".equalsIgnoreCase(mimeParts[i])) {
|
||||
base64 = true;
|
||||
}
|
||||
}
|
||||
String dataPartAsString = uriAsString.substring(commaPos + 1);
|
||||
byte[] data;
|
||||
if (base64) {
|
||||
data = Base64.decode(dataPartAsString, Base64.DEFAULT);
|
||||
} else {
|
||||
try {
|
||||
data = dataPartAsString.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
data = dataPartAsString.getBytes();
|
||||
}
|
||||
}
|
||||
InputStream inputStream = new ByteArrayInputStream(data);
|
||||
return new OpenForReadResult(uri, inputStream, contentType, data.length, null);
|
||||
}
|
||||
|
||||
private static void assertNonRelative(Uri uri) {
|
||||
if (!uri.isAbsolute()) {
|
||||
throw new IllegalArgumentException("Relative URIs are not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OpenForReadResult {
|
||||
public final Uri uri;
|
||||
public final InputStream inputStream;
|
||||
public final String mimeType;
|
||||
public final long length;
|
||||
public final AssetFileDescriptor assetFd;
|
||||
|
||||
public OpenForReadResult(Uri uri, InputStream inputStream, String mimeType, long length, AssetFileDescriptor assetFd) {
|
||||
this.uri = uri;
|
||||
this.inputStream = inputStream;
|
||||
this.mimeType = mimeType;
|
||||
this.length = length;
|
||||
this.assetFd = assetFd;
|
||||
}
|
||||
}
|
||||
}
|
||||
796
framework/src/org/apache/cordova/CordovaWebView.java
Executable file → Normal file
@@ -6,9 +6,7 @@
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@@ -16,759 +14,129 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.cordova.api.CordovaInterface;
|
||||
import org.apache.cordova.api.LOG;
|
||||
import org.apache.cordova.api.PluginManager;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebSettings.LayoutAlgorithm;
|
||||
import android.view.View;
|
||||
import android.webkit.WebChromeClient.CustomViewCallback;
|
||||
|
||||
public class CordovaWebView extends WebView {
|
||||
/**
|
||||
* Main interface for interacting with a Cordova webview - implemented by CordovaWebViewImpl.
|
||||
* This is an interface so that it can be easily mocked in tests.
|
||||
* Methods may be added to this interface without a major version bump, as plugins & embedders
|
||||
* are not expected to implement it.
|
||||
*/
|
||||
public interface CordovaWebView {
|
||||
public static final String CORDOVA_VERSION = "10.0.0-dev";
|
||||
|
||||
public static final String TAG = "CordovaWebView";
|
||||
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);
|
||||
|
||||
/** The whitelist **/
|
||||
private ArrayList<Pattern> whiteList = new ArrayList<Pattern>();
|
||||
private HashMap<String, Boolean> whiteListCache = new HashMap<String, Boolean>();
|
||||
private ArrayList<Integer> keyDownCodes = new ArrayList<Integer>();
|
||||
private ArrayList<Integer> keyUpCodes = new ArrayList<Integer>();
|
||||
|
||||
public PluginManager pluginManager;
|
||||
public CallbackServer callbackServer;
|
||||
|
||||
boolean isInitialized();
|
||||
|
||||
/** Actvities and other important classes **/
|
||||
private CordovaInterface mCtx;
|
||||
CordovaWebViewClient viewClient;
|
||||
@SuppressWarnings("unused")
|
||||
private CordovaChromeClient chromeClient;
|
||||
View getView();
|
||||
|
||||
//This is for the polyfil history
|
||||
private String url;
|
||||
String baseUrl;
|
||||
private Stack<String> urls = new Stack<String>();
|
||||
void loadUrlIntoView(String url, boolean recreatePlugins);
|
||||
|
||||
boolean useBrowserHistory = false;
|
||||
void stopLoading();
|
||||
|
||||
// Flag to track that a loadUrl timeout occurred
|
||||
int loadUrlTimeout = 0;
|
||||
boolean canGoBack();
|
||||
|
||||
private boolean bound;
|
||||
void clearCache();
|
||||
|
||||
private boolean volumedownBound;
|
||||
/** Use parameter-less overload */
|
||||
@Deprecated
|
||||
void clearCache(boolean b);
|
||||
|
||||
private boolean volumeupBound;
|
||||
void clearHistory();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public CordovaWebView(Context context) {
|
||||
super(context);
|
||||
if (CordovaInterface.class.isInstance(context))
|
||||
{
|
||||
this.mCtx = (CordovaInterface) context;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.d(TAG, "Your activity must implement CordovaInterface to work");
|
||||
}
|
||||
this.loadConfiguration();
|
||||
this.setup();
|
||||
}
|
||||
boolean backHistory();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
public CordovaWebView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
if (CordovaInterface.class.isInstance(context))
|
||||
{
|
||||
this.mCtx = (CordovaInterface) context;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.d(TAG, "Your activity must implement CordovaInterface to work");
|
||||
}
|
||||
this.setWebChromeClient(new CordovaChromeClient(this.mCtx, this));
|
||||
this.setWebViewClient(new CordovaWebViewClient(this.mCtx, this));
|
||||
this.loadConfiguration();
|
||||
this.setup();
|
||||
}
|
||||
void handlePause(boolean keepRunning);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
*
|
||||
*/
|
||||
public CordovaWebView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
if (CordovaInterface.class.isInstance(context))
|
||||
{
|
||||
this.mCtx = (CordovaInterface) context;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.d(TAG, "Your activity must implement CordovaInterface to work");
|
||||
}
|
||||
this.setWebChromeClient(new CordovaChromeClient(this.mCtx, this));
|
||||
this.setWebViewClient(new CordovaWebViewClient(this.mCtx, this));
|
||||
this.loadConfiguration();
|
||||
this.setup();
|
||||
}
|
||||
void onNewIntent(Intent intent);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
* @param privateBrowsing
|
||||
*/
|
||||
public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
|
||||
super(context, attrs, defStyle, privateBrowsing);
|
||||
if (CordovaInterface.class.isInstance(context))
|
||||
{
|
||||
this.mCtx = (CordovaInterface) context;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.d(TAG, "Your activity must implement CordovaInterface to work");
|
||||
}
|
||||
this.setWebChromeClient(new CordovaChromeClient(this.mCtx));
|
||||
this.setWebViewClient(new CordovaWebViewClient(this.mCtx));
|
||||
this.loadConfiguration();
|
||||
this.setup();
|
||||
}
|
||||
void handleResume(boolean keepRunning);
|
||||
|
||||
/**
|
||||
* Initialize webview.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setup() {
|
||||
void handleStart();
|
||||
|
||||
this.setInitialScale(0);
|
||||
this.setVerticalScrollBarEnabled(false);
|
||||
this.requestFocusFromTouch();
|
||||
void handleStop();
|
||||
|
||||
// Enable JavaScript
|
||||
WebSettings settings = this.getSettings();
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setJavaScriptCanOpenWindowsAutomatically(true);
|
||||
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
|
||||
|
||||
//Set the nav dump for HTC
|
||||
settings.setNavDump(true);
|
||||
|
||||
// Enable database
|
||||
settings.setDatabaseEnabled(true);
|
||||
String databasePath = this.mCtx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
|
||||
settings.setDatabasePath(databasePath);
|
||||
|
||||
// Enable DOM storage
|
||||
settings.setDomStorageEnabled(true);
|
||||
|
||||
// Enable built-in geolocation
|
||||
settings.setGeolocationEnabled(true);
|
||||
|
||||
//Start up the plugin manager
|
||||
try {
|
||||
this.pluginManager = new PluginManager(this, this.mCtx);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the WebViewClient.
|
||||
*
|
||||
* @param client
|
||||
*/
|
||||
public void setWebViewClient(CordovaWebViewClient client) {
|
||||
this.viewClient = client;
|
||||
super.setWebViewClient(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the WebChromeClient.
|
||||
*
|
||||
* @param client
|
||||
*/
|
||||
public void setWebChromeClient(CordovaChromeClient client) {
|
||||
this.chromeClient = client;
|
||||
super.setWebChromeClient(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add entry to approved list of URLs (whitelist)
|
||||
*
|
||||
* @param origin URL regular expression to allow
|
||||
* @param subdomains T=include all subdomains under origin
|
||||
*/
|
||||
public void addWhiteListEntry(String origin, boolean subdomains) {
|
||||
try {
|
||||
// Unlimited access to network resources
|
||||
if (origin.compareTo("*") == 0) {
|
||||
LOG.d(TAG, "Unlimited access to network resources");
|
||||
this.whiteList.add(Pattern.compile(".*"));
|
||||
} else { // specific access
|
||||
// check if subdomains should be included
|
||||
// TODO: we should not add more domains if * has already been added
|
||||
if (subdomains) {
|
||||
// XXX making it stupid friendly for people who forget to include protocol/SSL
|
||||
if (origin.startsWith("http")) {
|
||||
this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?")));
|
||||
} else {
|
||||
this.whiteList.add(Pattern.compile("^https?://(.*\\.)?" + origin));
|
||||
}
|
||||
LOG.d(TAG, "Origin to allow with subdomains: %s", origin);
|
||||
} else {
|
||||
// XXX making it stupid friendly for people who forget to include protocol/SSL
|
||||
if (origin.startsWith("http")) {
|
||||
this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://")));
|
||||
} else {
|
||||
this.whiteList.add(Pattern.compile("^https?://" + origin));
|
||||
}
|
||||
LOG.d(TAG, "Origin to allow: %s", origin);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.d(TAG, "Failed to add origin %s", origin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if URL is in approved list of URLs to load.
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public boolean isUrlWhiteListed(String url) {
|
||||
|
||||
// Check to see if we have matched url previously
|
||||
if (this.whiteListCache.get(url) != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for match in white list
|
||||
Iterator<Pattern> pit = this.whiteList.iterator();
|
||||
while (pit.hasNext()) {
|
||||
Pattern p = pit.next();
|
||||
Matcher m = p.matcher(url);
|
||||
|
||||
// If match found, then cache it to speed up subsequent comparisons
|
||||
if (m.find()) {
|
||||
this.whiteListCache.put(url, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
@Override
|
||||
public void loadUrl(String url) {
|
||||
if (url.equals("about:blank") || url.startsWith("javascript:")) {
|
||||
this.loadUrlNow(url);
|
||||
}
|
||||
else {
|
||||
|
||||
String initUrl = this.getProperty("url", null);
|
||||
|
||||
// If first page of app, then set URL to load to be the one passed in
|
||||
if (initUrl == null || (this.urls.size() > 0)) {
|
||||
this.loadUrlIntoView(url);
|
||||
}
|
||||
// Otherwise use the URL specified in the activity's extras bundle
|
||||
else {
|
||||
this.loadUrlIntoView(initUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview after waiting for period of time.
|
||||
* This is used to display the splashscreen for certain amount of time.
|
||||
*
|
||||
* @param url
|
||||
* @param time The number of ms to wait before loading webview
|
||||
*/
|
||||
public void loadUrl(final String url, int time) {
|
||||
String initUrl = this.getProperty("url", null);
|
||||
|
||||
// If first page of app, then set URL to load to be the one passed in
|
||||
if (initUrl == null || (this.urls.size() > 0)) {
|
||||
this.loadUrlIntoView(url, time);
|
||||
}
|
||||
// Otherwise use the URL specified in the activity's extras bundle
|
||||
else {
|
||||
this.loadUrlIntoView(initUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public void loadUrlIntoView(final String url) {
|
||||
LOG.d(TAG, ">>> loadUrl(" + url + ")");
|
||||
|
||||
this.url = url;
|
||||
if (this.baseUrl == null) {
|
||||
int i = url.lastIndexOf('/');
|
||||
if (i > 0) {
|
||||
this.baseUrl = url.substring(0, i + 1);
|
||||
}
|
||||
else {
|
||||
this.baseUrl = this.url + "/";
|
||||
}
|
||||
|
||||
this.pluginManager.init();
|
||||
|
||||
if (!this.useBrowserHistory) {
|
||||
this.urls.push(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a timeout timer for loadUrl
|
||||
final CordovaWebView me = this;
|
||||
final int currentLoadUrlTimeout = me.loadUrlTimeout;
|
||||
final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("loadUrlTimeoutValue", "20000"));
|
||||
|
||||
// Timeout error method
|
||||
final Runnable loadError = new Runnable() {
|
||||
public void run() {
|
||||
me.stopLoading();
|
||||
LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
|
||||
if (viewClient != null) {
|
||||
viewClient.onReceivedError(me, -6, "The connection to the server was unsuccessful.", url);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Timeout timer method
|
||||
final Runnable timeoutCheck = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
synchronized (this) {
|
||||
wait(loadUrlTimeoutValue);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// If timeout, then stop loading and handle error
|
||||
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
|
||||
me.mCtx.getActivity().runOnUiThread(loadError);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Load url
|
||||
this.mCtx.getActivity().runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
Thread thread = new Thread(timeoutCheck);
|
||||
thread.start();
|
||||
me.loadUrlNow(url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load URL in webview.
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
private void loadUrlNow(String url) {
|
||||
LOG.d(TAG, ">>> loadUrlNow()");
|
||||
super.loadUrl(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview after waiting for period of time.
|
||||
* This is used to display the splashscreen for certain amount of time.
|
||||
*
|
||||
* @param url
|
||||
* @param time The number of ms to wait before loading webview
|
||||
*/
|
||||
public void loadUrlIntoView(final String url, final int time) {
|
||||
|
||||
// If not first page of app, then load immediately
|
||||
// Add support for browser history if we use it.
|
||||
if ((url.startsWith("javascript:")) || this.urls.size() > 0 || this.canGoBack()) {
|
||||
}
|
||||
|
||||
// If first page, then show splashscreen
|
||||
else {
|
||||
|
||||
LOG.d(TAG, "DroidGap.loadUrl(%s, %d)", url, time);
|
||||
|
||||
// Send message to show splashscreen now if desired
|
||||
this.postMessage("splashscreen", "show");
|
||||
}
|
||||
|
||||
// Load url
|
||||
this.loadUrlIntoView(url);
|
||||
}
|
||||
void handleDestroy();
|
||||
|
||||
/**
|
||||
* Send JavaScript statement back to JavaScript.
|
||||
* (This is a convenience method)
|
||||
*
|
||||
* @param message
|
||||
*
|
||||
* Deprecated (https://issues.apache.org/jira/browse/CB-6851)
|
||||
* Instead of executing snippets of JS, you should use the exec bridge
|
||||
* to create a Java->JS communication channel.
|
||||
* To do this:
|
||||
* 1. Within plugin.xml (to have your JS run before deviceready):
|
||||
* <js-module><runs/></js-module>
|
||||
* 2. Within your .js (call exec on start-up):
|
||||
* require('cordova/channel').onCordovaReady.subscribe(function() {
|
||||
* require('cordova/exec')(win, null, 'Plugin', 'method', []);
|
||||
* function win(message) {
|
||||
* ... process message from java here ...
|
||||
* }
|
||||
* });
|
||||
* 3. Within your .java:
|
||||
* PluginResult dataResult = new PluginResult(PluginResult.Status.OK, CODE);
|
||||
* dataResult.setKeepCallback(true);
|
||||
* savedCallbackContext.sendPluginResult(dataResult);
|
||||
*/
|
||||
public void sendJavascript(String statement) {
|
||||
if (this.callbackServer != null) {
|
||||
this.callbackServer.sendJavascript(statement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to all plugins.
|
||||
*
|
||||
* @param id The message id
|
||||
* @param data The message data
|
||||
*/
|
||||
public void postMessage(String id, Object data) {
|
||||
if (this.pluginManager != null) {
|
||||
this.pluginManager.postMessage(id, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top url on the stack without removing it from
|
||||
* the stack.
|
||||
*/
|
||||
public String peekAtUrlStack() {
|
||||
if (this.urls.size() > 0) {
|
||||
return this.urls.peek();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a url to the stack
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public void pushUrl(String url) {
|
||||
this.urls.push(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to previous page in history. (We manage our own history)
|
||||
*
|
||||
* @return true if we went back, false if we are already at top
|
||||
*/
|
||||
public boolean backHistory() {
|
||||
|
||||
// Check webview first to see if there is a history
|
||||
// This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
|
||||
if (super.canGoBack()) {
|
||||
super.goBack();
|
||||
return true;
|
||||
}
|
||||
|
||||
// If our managed history has prev url
|
||||
if (this.urls.size() > 1) {
|
||||
this.urls.pop(); // Pop current url
|
||||
String url = this.urls.pop(); // Pop prev url that we want to load, since it will be added back by loadUrl()
|
||||
this.loadUrl(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there is a history item.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean canGoBack() {
|
||||
if (super.canGoBack()) {
|
||||
return true;
|
||||
}
|
||||
if (this.urls.size() > 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Deprecated
|
||||
void sendJavascript(String statememt);
|
||||
|
||||
/**
|
||||
* Load the specified URL in the Cordova webview or a new browser instance.
|
||||
*
|
||||
* NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
|
||||
*
|
||||
* NOTE: If openExternal is false, only allow listed URLs can be loaded.
|
||||
*
|
||||
* @param url The url to load.
|
||||
* @param openExternal Load url in browser instead of Cordova webview.
|
||||
* @param clearHistory Clear the history stack, so new page becomes top of history
|
||||
* @param params DroidGap parameters for new app
|
||||
* @param params Parameters for new app
|
||||
*/
|
||||
public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
|
||||
LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
|
||||
|
||||
// If clearing history
|
||||
if (clearHistory) {
|
||||
this.clearHistory();
|
||||
}
|
||||
|
||||
// If loading into our webview
|
||||
if (!openExternal) {
|
||||
|
||||
// Make sure url is in whitelist
|
||||
if (url.startsWith("file://") || url.indexOf(this.baseUrl) == 0 || isUrlWhiteListed(url)) {
|
||||
// TODO: What about params?
|
||||
|
||||
// Clear out current url from history, since it will be replacing it
|
||||
if (clearHistory) {
|
||||
this.urls.clear();
|
||||
}
|
||||
|
||||
// Load new URL
|
||||
this.loadUrl(url);
|
||||
}
|
||||
// Load in default viewer if not
|
||||
else {
|
||||
LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list. Loading into browser instead. (URL=" + url + ")");
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
mCtx.getActivity().startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error loading url " + url, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load in default view intent
|
||||
else {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
mCtx.getActivity().startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error loading url " + url, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
void showWebPage(String url, boolean openExternal, boolean clearHistory, Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* Load Cordova configuration from res/xml/cordova.xml.
|
||||
* Approved list of URLs that can be loaded into DroidGap
|
||||
* <access origin="http://server regexp" subdomains="true" />
|
||||
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
|
||||
* <log level="DEBUG" />
|
||||
* Deprecated in 4.0.0. Use your own View-toggling logic.
|
||||
*/
|
||||
private void loadConfiguration() {
|
||||
int id = getResources().getIdentifier("cordova", "xml", this.mCtx.getActivity().getPackageName());
|
||||
if (id == 0) {
|
||||
LOG.i("CordovaLog", "cordova.xml missing. Ignoring...");
|
||||
return;
|
||||
}
|
||||
XmlResourceParser xml = getResources().getXml(id);
|
||||
int eventType = -1;
|
||||
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
||||
if (eventType == XmlResourceParser.START_TAG) {
|
||||
String strNode = xml.getName();
|
||||
if (strNode.equals("access")) {
|
||||
String origin = xml.getAttributeValue(null, "origin");
|
||||
String subdomains = xml.getAttributeValue(null, "subdomains");
|
||||
if (origin != null) {
|
||||
this.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
||||
}
|
||||
}
|
||||
else if (strNode.equals("log")) {
|
||||
String level = xml.getAttributeValue(null, "level");
|
||||
LOG.i("CordovaLog", "Found log level %s", level);
|
||||
if (level != null) {
|
||||
LOG.setLogLevel(level);
|
||||
}
|
||||
}
|
||||
else if (strNode.equals("preference")) {
|
||||
String name = xml.getAttributeValue(null, "name");
|
||||
String value = xml.getAttributeValue(null, "value");
|
||||
|
||||
LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
|
||||
|
||||
// Save preferences in Intent
|
||||
this.mCtx.getActivity().getIntent().putExtra(name, value);
|
||||
}
|
||||
}
|
||||
try {
|
||||
eventType = xml.next();
|
||||
} catch (XmlPullParserException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Init preferences
|
||||
if ("true".equals(this.getProperty("useBrowserHistory", "true"))) {
|
||||
this.useBrowserHistory = true;
|
||||
}
|
||||
else {
|
||||
this.useBrowserHistory = false;
|
||||
}
|
||||
|
||||
if ("true".equals(this.getProperty("fullscreen", "false"))) {
|
||||
this.mCtx.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
this.mCtx.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
@Deprecated
|
||||
boolean isCustomViewShowing();
|
||||
|
||||
/**
|
||||
* Get string property for activity.
|
||||
*
|
||||
* @param name
|
||||
* @param defaultValue
|
||||
* @return
|
||||
* Deprecated in 4.0.0. Use your own View-toggling logic.
|
||||
*/
|
||||
public String getProperty(String name, String defaultValue) {
|
||||
Bundle bundle = this.mCtx.getActivity().getIntent().getExtras();
|
||||
if (bundle == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
Object p = bundle.get(name);
|
||||
if (p == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return p.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* onKeyDown
|
||||
@Deprecated
|
||||
void showCustomView(View view, CustomViewCallback callback);
|
||||
|
||||
/**
|
||||
* Deprecated in 4.0.0. Use your own View-toggling logic.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event)
|
||||
{
|
||||
if(keyDownCodes.contains(keyCode))
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
||||
// only override default behaviour is event bound
|
||||
LOG.d(TAG, "Down Key Hit");
|
||||
this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
|
||||
return true;
|
||||
}
|
||||
// If volumeup key
|
||||
else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
|
||||
LOG.d(TAG, "Up Key Hit");
|
||||
this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do some other stuff!
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event)
|
||||
{
|
||||
|
||||
Log.d(TAG, "KeyDown has been triggered on the view");
|
||||
@Deprecated
|
||||
void hideCustomView();
|
||||
|
||||
// If back key
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
// If back key is bound, then send event to JavaScript
|
||||
if (this.bound) {
|
||||
this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
|
||||
return true;
|
||||
} else {
|
||||
// If not bound
|
||||
// Go to previous page in webview if it is possible to go back
|
||||
if (this.backHistory()) {
|
||||
return true;
|
||||
}
|
||||
// If not, then invoke default behaviour
|
||||
else {
|
||||
//this.activityState = ACTIVITY_EXITING;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Legacy
|
||||
else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
// If search key
|
||||
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
||||
this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
|
||||
return true;
|
||||
}
|
||||
else if(keyUpCodes.contains(keyCode))
|
||||
{
|
||||
//What the hell should this do?
|
||||
}
|
||||
CordovaResourceApi getResourceApi();
|
||||
|
||||
|
||||
Log.d(TAG, "KeyUp has been triggered on the view");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void bindButton(boolean override)
|
||||
{
|
||||
this.bound = override;
|
||||
}
|
||||
|
||||
public void bindButton(String button, boolean override) {
|
||||
// TODO Auto-generated method stub
|
||||
if (button.compareTo("volumeup")==0) {
|
||||
keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP);
|
||||
}
|
||||
else if (button.compareTo("volumedown")==0) {
|
||||
keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
public void bindButton(int keyCode, boolean keyDown, boolean override) {
|
||||
if(keyDown)
|
||||
{
|
||||
keyDownCodes.add(keyCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyUpCodes.add(keyCode);
|
||||
}
|
||||
}
|
||||
void setButtonPlumbedToJs(int keyCode, boolean override);
|
||||
boolean isButtonPlumbedToJs(int keyCode);
|
||||
|
||||
void sendPluginResult(PluginResult cr, String callbackId);
|
||||
|
||||
PluginManager getPluginManager();
|
||||
CordovaWebViewEngine getEngine();
|
||||
CordovaPreferences getPreferences();
|
||||
ICordovaCookieManager getCookieManager();
|
||||
|
||||
String getUrl();
|
||||
|
||||
// TODO: Work on deleting these by removing refs from plugins.
|
||||
Context getContext();
|
||||
void loadUrl(String url);
|
||||
Object postMessage(String id, Object data);
|
||||
}
|
||||
|
||||