Compare commits
217 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d0e8fa436 | ||
|
|
9d26598334 | ||
|
|
a688319ea7 | ||
|
|
bbf10e3baa | ||
|
|
7e70d76232 | ||
|
|
04b3e4d847 | ||
|
|
dc93556ef0 | ||
|
|
692a59a692 | ||
|
|
df691518e3 | ||
|
|
8f2cdcc049 | ||
|
|
d27064794c | ||
|
|
8a7af93765 | ||
|
|
f3c96ce1a0 | ||
|
|
715c0a5bea | ||
|
|
4b05ead3ac | ||
|
|
b4292868eb | ||
|
|
c5025ee2bb | ||
|
|
8923e52a5e | ||
|
|
aa4f2cc4d9 | ||
|
|
4a23f86411 | ||
|
|
a69bd65152 | ||
|
|
7392b63b99 | ||
|
|
73aa5cc7c3 | ||
|
|
7bf35e9c83 | ||
|
|
adb871f9e1 | ||
|
|
21b7346277 | ||
|
|
79935d31ef | ||
|
|
d2fc08959a | ||
|
|
3ebc1d71df | ||
|
|
f6503f8476 | ||
|
|
d593448182 | ||
|
|
403b87b68b | ||
|
|
bf69362709 | ||
|
|
c00fb987f6 | ||
|
|
7c6450de50 | ||
|
|
10cbcd7f5a | ||
|
|
e918ffd751 | ||
|
|
3ed41597d2 | ||
|
|
5722d976ce | ||
|
|
8555c42196 | ||
|
|
e85394dd99 | ||
|
|
cc5cfad58d | ||
|
|
363b1429e3 | ||
|
|
900ff9ed2c | ||
|
|
c9d4276207 | ||
|
|
fef0e429db | ||
|
|
26044ad662 | ||
|
|
42430d5d11 | ||
|
|
770a257ed3 | ||
|
|
9fe1f21c9f | ||
|
|
49d8d22d7f | ||
|
|
d274891c2c | ||
|
|
c099c65365 | ||
|
|
79ba28d6c4 | ||
|
|
b4d1ca6181 | ||
|
|
657faaff7f | ||
|
|
a43e80ae1d | ||
|
|
5253b5fb31 | ||
|
|
8b12bf79e4 | ||
|
|
45d75524c9 | ||
|
|
8a137395ae | ||
|
|
390fe537f8 | ||
|
|
40cd71484c | ||
|
|
9188773152 | ||
|
|
cc8edea065 | ||
|
|
14b368e731 | ||
|
|
4d03577220 | ||
|
|
040619cd61 | ||
|
|
d6fef8d6e3 | ||
|
|
7c1eb7da9b | ||
|
|
d87ee719a3 | ||
|
|
a52ba37cf7 | ||
|
|
cd667d6af5 | ||
|
|
7e4158ce94 | ||
|
|
0ba803ff46 | ||
|
|
6c48c6a3a1 | ||
|
|
7ee135e516 | ||
|
|
fd69095d3d | ||
|
|
357c0ee1ca | ||
|
|
40637c1486 | ||
|
|
a84d2eab02 | ||
|
|
52213541a3 | ||
|
|
c7d4d83476 | ||
|
|
003e3d4d85 | ||
|
|
95b9cd0229 | ||
|
|
044a61d881 | ||
|
|
9aa1cd756a | ||
|
|
ee4c91539a | ||
|
|
77547f8826 | ||
|
|
52a3a919f9 | ||
|
|
1293d64589 | ||
|
|
54968b755b | ||
|
|
d8d7c29afe | ||
|
|
1c7626aba2 | ||
|
|
e0fea2c352 | ||
|
|
210cc2bd5e | ||
|
|
664a061d10 | ||
|
|
fa4d6d369a | ||
|
|
3bff8aec88 | ||
|
|
e64cb2fc4f | ||
|
|
c5ada0f09f | ||
|
|
44edcbb3cf | ||
|
|
3fd2f590fd | ||
|
|
4f61531422 | ||
|
|
6e82ec4152 | ||
|
|
9206dca741 | ||
|
|
503640f6b5 | ||
|
|
e1e04f859c | ||
|
|
e30896155c | ||
|
|
282f59cd99 | ||
|
|
89e260a5a1 | ||
|
|
20891aee1a | ||
|
|
6e5ef1e819 | ||
|
|
e8544d30d1 | ||
|
|
f9af33b750 | ||
|
|
d28a60ed97 | ||
|
|
0890be5815 | ||
|
|
308a5f1509 | ||
|
|
7904bcc054 | ||
|
|
c7e3b46e2e | ||
|
|
490a13d3c4 | ||
|
|
1dfe7e59a7 | ||
|
|
a2cdcd47be | ||
|
|
a42451969f | ||
|
|
7955c6dd02 | ||
|
|
56096ad00e | ||
|
|
faacdd6b02 | ||
|
|
bdd7449af3 | ||
|
|
64c462c8ad | ||
|
|
cb0b054079 | ||
|
|
41b49df944 | ||
|
|
ffa76246e3 | ||
|
|
3af4d6b139 | ||
|
|
752b1b0e30 | ||
|
|
d91beb5ad9 | ||
|
|
8db5e06c62 | ||
|
|
bc309c9f00 | ||
|
|
9078fe17b5 | ||
|
|
3172ae4525 | ||
|
|
58774addad | ||
|
|
8c191331ae | ||
|
|
7f7c211769 | ||
|
|
51bf8c39af | ||
|
|
4bba9ac5a0 | ||
|
|
e9eb08486a | ||
|
|
3466ef6dfd | ||
|
|
36bca7d609 | ||
|
|
cc04b54adf | ||
|
|
e96ae91800 | ||
|
|
1d5af102c7 | ||
|
|
b106d2cae8 | ||
|
|
c66142d6b8 | ||
|
|
5fac30ea34 | ||
|
|
fae551f0ce | ||
|
|
65e3a8a453 | ||
|
|
1511183dfd | ||
|
|
a640804897 | ||
|
|
f95fdb5873 | ||
|
|
4b9e50146e | ||
|
|
26408fabe4 | ||
|
|
1dfc65face | ||
|
|
18bf4cd94b | ||
|
|
729d141c3f | ||
|
|
29001eeb3a | ||
|
|
acc9173e6e | ||
|
|
f387720e54 | ||
|
|
2094854588 | ||
|
|
8dbb8f58b1 | ||
|
|
75963c88d5 | ||
|
|
188e3e7d7d | ||
|
|
e02322b66b | ||
|
|
8904c67fb5 | ||
|
|
feff655530 | ||
|
|
71ea25f40a | ||
|
|
7840448133 | ||
|
|
e77e552293 | ||
|
|
5ceb6e2cfa | ||
|
|
035ad08c69 | ||
|
|
80d0a0cb4c | ||
|
|
05e233bf1d | ||
|
|
853a734f82 | ||
|
|
d5580557f1 | ||
|
|
7a6a59383b | ||
|
|
c70a1e8594 | ||
|
|
cd5bf6195e | ||
|
|
7c8db0ea44 | ||
|
|
119f6cca85 | ||
|
|
4a25d780ce | ||
|
|
798cb3e347 | ||
|
|
63ae953432 | ||
|
|
36caaf366f | ||
|
|
3ebfb6717c | ||
|
|
9409caad69 | ||
|
|
5406d6c98f | ||
|
|
29c7e12505 | ||
|
|
cbdd400fe7 | ||
|
|
a6db1112c6 | ||
|
|
bfef72a7c4 | ||
|
|
7ce2a8cb71 | ||
|
|
2a866e2a7c | ||
|
|
827af8a920 | ||
|
|
0caca9ae55 | ||
|
|
0bbcf5cfd2 | ||
|
|
fd93404c7c | ||
|
|
e9fcb296bb | ||
|
|
d5d95ad489 | ||
|
|
db0a1919f3 | ||
|
|
141b8355ac | ||
|
|
affab67ca3 | ||
|
|
cf9848bd59 | ||
|
|
7ad3f76d9a | ||
|
|
7244a5a727 | ||
|
|
538cdb03fc | ||
|
|
e1d3f1491f | ||
|
|
5075a3e087 | ||
|
|
a35a33c05e | ||
|
|
5a40613ccc |
11
.gitignore
vendored
@@ -1,15 +1,18 @@
|
||||
.DS_Store
|
||||
default.properties
|
||||
gen
|
||||
assets/www/phonegap.js
|
||||
assets/www/cordova.js
|
||||
local.properties
|
||||
framework/proguard.cfg
|
||||
framework/phonegap.jar
|
||||
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
|
||||
example
|
||||
test
|
||||
./test
|
||||
tmp
|
||||
*.tmp
|
||||
*.tmp
|
||||
|
||||
244
LICENSE
@@ -1,64 +1,202 @@
|
||||
PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
MIT License (2008). As a recipient of PhonegGap, you may choose which
|
||||
license to receive this code under (except as noted in per-module LICENSE
|
||||
files). Some modules may not be the copyright of Nitobi. These
|
||||
modules contain explicit declarations of copyright in both the LICENSE files in
|
||||
the directories in which they reside and in the code itself. No external
|
||||
contributions are allowed under licenses which are fundamentally incompatible
|
||||
with the MIT or BSD licenses that PhoneGap is distributed under.
|
||||
|
||||
The text of the MIT and BSD licenses is reproduced below.
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
The "New" BSD License:
|
||||
**********************
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
All rights reserved.
|
||||
1. Definitions.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of Phonegap/Nitobi nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
The MIT License
|
||||
*****************
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
Copyright (c) <2010> <Nitobi Software Inc., et. al., >
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
5
NOTICE
Normal file
@@ -0,0 +1,5 @@
|
||||
Apache Callback
|
||||
Copyright 2011 The Apache Software Foundation
|
||||
|
||||
This product includes software developed by
|
||||
The Apache Software Foundation (http://www.apache.org)
|
||||
47
README.md
@@ -1,7 +1,16 @@
|
||||
PhoneGap Android
|
||||
Cordova Android
|
||||
===
|
||||
|
||||
PhoneGap Android is an Android application library that allows for PhoneGap based projects to be built for the Android Platform. PhoneGap based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Requires
|
||||
---
|
||||
@@ -10,25 +19,35 @@ Requires
|
||||
- Apache ANT
|
||||
- Android SDK [http://developer.android.com](http://developer.android.com)
|
||||
|
||||
PhoneGap Android Developer Tools
|
||||
|
||||
Building
|
||||
---
|
||||
|
||||
The PhoneGap developer tooling is split between general tooling and project level tooling.
|
||||
To create your cordova.jar, run in the framework directory:
|
||||
|
||||
android update project -p . -t android-15
|
||||
ant jar
|
||||
|
||||
|
||||
Cordova Android Developer Tools
|
||||
---
|
||||
|
||||
The Cordova developer tooling is split between general tooling and project level tooling.
|
||||
|
||||
General Commands
|
||||
|
||||
./bin/create [path package activity] ... create the ./example app or a phonegap android project
|
||||
./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 PhoneGap Android project.
|
||||
These commands live in a generated Cordova Android project.
|
||||
|
||||
./phonegap/debug [path] ..................... install to first device
|
||||
./phonegap/emulate .......................... start avd (emulator) named default
|
||||
./phonegap/log .............................. starts logcat
|
||||
./cordovap/debug [path] ..................... install to first device
|
||||
./cordova/emulate .......................... start avd (emulator) named default
|
||||
./cordova/log .............................. starts logcat
|
||||
|
||||
Running the Example Project
|
||||
---
|
||||
@@ -41,29 +60,29 @@ Create the example project and build it to the first device:
|
||||
|
||||
./bin/create
|
||||
cd example
|
||||
./phonegap/debug
|
||||
./cordova/debug
|
||||
|
||||
Start adb logcat (console.log calls output here):
|
||||
|
||||
./phonegap/log
|
||||
./cordova/log
|
||||
|
||||
Running the [callback/callback-test](http://github.com/callback/callback-test) tests:
|
||||
---
|
||||
|
||||
./bin/test
|
||||
|
||||
Creating a new PhoneGap Android Project
|
||||
Creating a new Cordova Android Project
|
||||
---
|
||||
|
||||
./bin/create ~/Desktop/myapp com.phonegap.special MyApp
|
||||
|
||||
Importing a PhoneGap Android Project into Eclipse
|
||||
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/phonegap.jar and add to build path
|
||||
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)
|
||||
|
||||
|
||||
2
bin/BOOM
@@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
|
||||
./bin/create
|
||||
cd ./example && ./phonegap/debug && ./phonegap/log
|
||||
cd ./example && ./cordova/debug && ./cordova/log
|
||||
|
||||
12
bin/bench
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Creates an app in `./bench` that posts results to http://phonegap-bench.heroku.com with current PhoneGap/Android sha.
|
||||
# Creates an app in `./bench` that posts results to http://cordova-bench.heroku.com with current cordova/Android sha.
|
||||
#
|
||||
# USAGE
|
||||
# ./bin/bench
|
||||
@@ -13,17 +13,17 @@ then
|
||||
fi
|
||||
|
||||
# create a benching app
|
||||
./bin/create ./bench com.phonegap.bench PhoneGapBench
|
||||
./bin/create ./bench org.apache.cordova.bench cordovaBench
|
||||
|
||||
# grab the latest bench www code
|
||||
git clone git@github.com:brianleroux/phonegap-bench.git
|
||||
git clone git@github.com:brianleroux/cordova-bench.git
|
||||
|
||||
# copy it into the app
|
||||
cat ./phonegap-bench/www/index.html > ./bench/assets/www/index.html
|
||||
#cat ~/Desktop/phonegap-bench/www/index.html > ./bench/assets/www/index.html
|
||||
cat ./cordova-bench/www/index.html > ./bench/assets/www/index.html
|
||||
#cat ~/Desktop/cordova-bench/www/index.html > ./bench/assets/www/index.html
|
||||
|
||||
# clean up
|
||||
rm -rf ./phonegap-bench
|
||||
rm -rf ./cordova-bench
|
||||
|
||||
# launch to the first device found
|
||||
./bin/debug ./bench
|
||||
|
||||
22
bin/create
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# create a phonegap/android project
|
||||
# create a cordova/android project
|
||||
#
|
||||
# USAGE
|
||||
# ./create [path package activity]
|
||||
@@ -8,8 +8,8 @@
|
||||
set -e
|
||||
|
||||
PROJECT_PATH=${1:-"./example"}
|
||||
PACKAGE=${2:-"com.phonegap.example"}
|
||||
ACTIVITY=${3:-"PhoneGapExample"}
|
||||
PACKAGE=${2:-"org.apache.cordova.example"}
|
||||
ACTIVITY=${3:-"cordovaExample"}
|
||||
TARGET=$(android list targets | grep 'id: ' | sed 's/id: \([0-9]*\).*/\1/g' | tail -1)
|
||||
VERSION=$(cat ./VERSION)
|
||||
|
||||
@@ -19,23 +19,23 @@ then
|
||||
rm -rf $PROJECT_PATH
|
||||
fi
|
||||
|
||||
# update the phonegap-android framework for the desired target
|
||||
# update the cordova-android framework for the desired target
|
||||
android update project --target $TARGET --path ./framework
|
||||
|
||||
# compile phonegap.js and phonegap.jar
|
||||
# compile cordova.js and cordova.jar
|
||||
cd ./framework && ant jar && cd ../
|
||||
|
||||
# copy all the bin scripts etc in there
|
||||
cp -R ./bin/templates/project/ $PROJECT_PATH
|
||||
|
||||
# copy in phonegap.js
|
||||
cp ./framework/assets/www/phonegap-$VERSION.js $PROJECT_PATH/.phonegap/android/phonegap-$VERSION.js
|
||||
# copy in cordova.js
|
||||
cp ./framework/assets/www/cordova-$VERSION.js $PROJECT_PATH/.cordova/android/cordova-$VERSION.js
|
||||
|
||||
# copy in phonegap.jar
|
||||
cp ./framework/phonegap-$VERSION.jar $PROJECT_PATH/.phonegap/android/phonegap-$VERSION.jar
|
||||
# copy in cordova.jar
|
||||
cp ./framework/cordova-$VERSION.jar $PROJECT_PATH/.cordova/android/cordova-$VERSION.jar
|
||||
|
||||
# app properties
|
||||
cat > $PROJECT_PATH/.phonegap/config <<eom
|
||||
cat > $PROJECT_PATH/.cordova/config <<eom
|
||||
VERSION=$VERSION
|
||||
PROJECT_PATH=$PROJECT_PATH
|
||||
PACKAGE=$PACKAGE
|
||||
@@ -43,4 +43,4 @@ ACTIVITY=$ACTIVITY
|
||||
TARGET=$TARGET
|
||||
eom
|
||||
|
||||
(cd $PROJECT_PATH && ./phonegap/create)
|
||||
(cd $PROJECT_PATH && ./cordova/create)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* create a phonegap/android project
|
||||
* create a cordova/android project
|
||||
*
|
||||
* USAGE
|
||||
* ./create [path package activity]
|
||||
@@ -26,7 +26,7 @@ function exec(s) {
|
||||
}
|
||||
|
||||
var args = WScript.Arguments, PROJECT_PATH="example",
|
||||
PACKAGE="com.phonegap.example", ACTIVITY="PhoneGapExample",
|
||||
PACKAGE="org.apache.cordova.example", ACTIVITY="cordovaExample",
|
||||
shell=WScript.CreateObject("WScript.Shell");
|
||||
|
||||
if (args.Count() == 3) {
|
||||
@@ -54,10 +54,10 @@ fi
|
||||
// create the project
|
||||
exec('android.bat create project --target '+TARGET+' --path '+PROJECT_PATH+' --package '+PACKAGE+' --activity '+ACTIVITY);
|
||||
|
||||
// update the phonegap framework project to a target that exists on this machine
|
||||
// update the cordova framework project to a target that exists on this machine
|
||||
exec('android.bat update project --target '+TARGET+' --path framework');
|
||||
|
||||
// compile phonegap.js and phonegap.jar
|
||||
// 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
|
||||
exec('ant.bat -f framework\\build.xml jar');
|
||||
@@ -65,11 +65,11 @@ exec('ant.bat -f framework\\build.xml jar');
|
||||
// copy in the project template
|
||||
exec('cmd /c xcopy bin\\templates\\project '+PROJECT_PATH+' /S /Y');
|
||||
|
||||
// copy in phonegap.js
|
||||
exec('cmd /c copy framework\\assets\\www\\phonegap-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\phonegap-'+VERSION+'.js /Y');
|
||||
// copy in cordova.js
|
||||
exec('cmd /c copy framework\\assets\\www\\cordova-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\cordova-'+VERSION+'.js /Y');
|
||||
|
||||
// copy in phonegap.jar
|
||||
exec('cmd /c copy framework\\phonegap-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\phonegap-'+VERSION+'.jar /Y');
|
||||
// copy in cordova.jar
|
||||
exec('cmd /c copy framework\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y');
|
||||
|
||||
// copy in default activity
|
||||
exec('cmd /c copy bin\\templates\\Activity.java '+ACTIVITY_PATH+' /Y');
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="PhoneGap" default="create" basedir="../">
|
||||
<project name="cordova" default="create" basedir="../">
|
||||
|
||||
<property name="project.path" value="${basedir}/example"/>
|
||||
<property name="package" value="com.phonegap.example"/>
|
||||
<property name="activity" value="PhoneGapExample"/>
|
||||
<property name="package" value="org.apache.cordova.example"/>
|
||||
<property name="activity" value="cordovaExample"/>
|
||||
|
||||
<target name="create">
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<arg line="update project --target ${target} --path ${basedir}/framework"/>
|
||||
</exec>
|
||||
|
||||
<!-- compile phonegap.js and phonegap.jar -->
|
||||
<!-- 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" />
|
||||
@@ -60,11 +60,11 @@
|
||||
<fileset dir="${basedir}/bin/templates/project"/>
|
||||
</copy>
|
||||
|
||||
<!-- copy in phonegap.js -->
|
||||
<copy file="${basedir}/framework/assets/www/phonegap-${version}.js" todir="${project.path}/assets/www/" />
|
||||
<!-- copy in cordova.js -->
|
||||
<copy file="${basedir}/framework/assets/www/cordova-${version}.js" todir="${project.path}/assets/www/" />
|
||||
|
||||
<!-- copy in phonegap.jar -->
|
||||
<copy file="${basedir}/framework/phonegap-${version}.jar" todir="${project.path}/libs/" />
|
||||
<!-- 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" />
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
this is local config for phonegap stuff to be eventually moved to
|
||||
this is local config for cordova stuff to be eventually moved to
|
||||
config.xml ...we think. feedback to @davejohnson/@brianleroux
|
||||
appreciated here!
|
||||
@@ -1,13 +1,13 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# create a phonegap/android project
|
||||
# create a cordova/android project
|
||||
#
|
||||
# USAGE
|
||||
# ./create [path package activity]
|
||||
#
|
||||
|
||||
# load up the config
|
||||
. ./.phonegap/config
|
||||
. ./.cordova/config
|
||||
|
||||
PACKAGE_AS_PATH=$(echo $PACKAGE | sed 's/\./\//g')
|
||||
ACTIVITY_PATH=./src/$PACKAGE_AS_PATH/$ACTIVITY.java
|
||||
@@ -16,21 +16,21 @@ MANIFEST_PATH=./AndroidManifest.xml
|
||||
# create the project
|
||||
android create project --target $TARGET --path . --package $PACKAGE --activity $ACTIVITY
|
||||
|
||||
# copy all the phonegap scripts etc in there
|
||||
cp -R ./phonegap/templates/project/* .
|
||||
# copy all the cordova scripts etc in there
|
||||
cp -R ./cordova/templates/project/* .
|
||||
|
||||
# copy in phonegap.js
|
||||
cp ./.phonegap/android/phonegap-$VERSION.js ./assets/www
|
||||
# copy in cordova.js
|
||||
cp ./.cordova/android/cordova-$VERSION.js ./assets/www
|
||||
|
||||
# copy in phonegap.jar
|
||||
cp ./.phonegap/android/phonegap-$VERSION.jar ./libs
|
||||
# copy in cordova.jar
|
||||
cp ./.cordova/android/cordova-$VERSION.jar ./libs
|
||||
|
||||
# copy in default activity
|
||||
cat ./phonegap/templates/Activity.java > $ACTIVITY_PATH
|
||||
cat ./cordova/templates/Activity.java > $ACTIVITY_PATH
|
||||
|
||||
# interpolate the acivity name and package
|
||||
find "$ACTIVITY_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i "s/__ACTIVITY__/${ACTIVITY}/g"
|
||||
find "$ACTIVITY_PATH" | xargs grep '__ID__' -sl | xargs -L1 sed -i "s/__ID__/${PACKAGE}/g"
|
||||
find "$ACTIVITY_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i -e "s/__ACTIVITY__/${ACTIVITY}/g"
|
||||
find "$ACTIVITY_PATH" | xargs grep '__ID__' -sl | xargs -L1 sed -i -e "s/__ID__/${PACKAGE}/g"
|
||||
|
||||
find "$MANIFEST_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i "s/__ACTIVITY__/${ACTIVITY}/g"
|
||||
find "$MANIFEST_PATH" | xargs grep '__PACKAGE__' -sl | xargs -L1 sed -i "s/__PACKAGE__/${PACKAGE}/g"
|
||||
find "$MANIFEST_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i -e "s/__ACTIVITY__/${ACTIVITY}/g"
|
||||
find "$MANIFEST_PATH" | xargs grep '__PACKAGE__' -sl | xargs -L1 sed -i -e "s/__PACKAGE__/${PACKAGE}/g"
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
|
||||
. ./.phonegap/config
|
||||
. ./.cordova/config
|
||||
|
||||
# if there are no devices listed then emulate
|
||||
|
||||
@@ -2,7 +2,7 @@ package __ID__;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import com.phonegap.*;
|
||||
import org.apache.cordova.*;
|
||||
|
||||
public class __ACTIVITY__ extends DroidGap
|
||||
{
|
||||
@@ -39,7 +39,7 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name"
|
||||
<activity android:name="org.apache.cordova.DroidGap" android:label="@string/app_name"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
</intent-filter>
|
||||
@@ -4,8 +4,8 @@
|
||||
<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" charset="utf-8">
|
||||
<script type="text/javascript" charset="utf-8" src="phonegap-1.2.0.js"></script>
|
||||
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
|
||||
<script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
||||
|
||||
</head>
|
||||
@@ -29,8 +29,12 @@
|
||||
<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();">Get Phone's Contacts</a>
|
||||
<a href="#" class="btn large" onclick="check_network();">Check Network</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>
|
||||
@@ -119,6 +119,25 @@ function check_network() {
|
||||
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
|
||||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
4
framework/res/xml/phonegap.xml → bin/templates/project/cordova/templates/project/res/xml/cordova.xml
Normal file → Executable file
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phonegap>
|
||||
<cordova>
|
||||
<access origin="http://127.0.0.1*"/>
|
||||
<log level="DEBUG"/>
|
||||
</phonegap>
|
||||
</cordova>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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="Network Status" 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"/>
|
||||
</plugins>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<phonegap>
|
||||
<access origin="http://127.0.0.1*"/>
|
||||
<log level="DEBUG"/>
|
||||
</phonegap>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<plugins>
|
||||
<plugin name="App" value="com.phonegap.App"/>
|
||||
<plugin name="Geolocation" value="com.phonegap.GeoBroker"/>
|
||||
<plugin name="Device" value="com.phonegap.Device"/>
|
||||
<plugin name="Accelerometer" value="com.phonegap.AccelListener"/>
|
||||
<plugin name="Compass" value="com.phonegap.CompassListener"/>
|
||||
<plugin name="Media" value="com.phonegap.AudioHandler"/>
|
||||
<plugin name="Camera" value="com.phonegap.CameraLauncher"/>
|
||||
<plugin name="Contacts" value="com.phonegap.ContactManager"/>
|
||||
<plugin name="Crypto" value="com.phonegap.CryptoHandler"/>
|
||||
<plugin name="File" value="com.phonegap.FileUtils"/>
|
||||
<plugin name="Network Status" value="com.phonegap.NetworkManager"/>
|
||||
<plugin name="Notification" value="com.phonegap.Notification"/>
|
||||
<plugin name="Storage" value="com.phonegap.Storage"/>
|
||||
<plugin name="Temperature" value="com.phonegap.TempListener"/>
|
||||
<plugin name="FileTransfer" value="com.phonegap.FileTransfer"/>
|
||||
<plugin name="Capture" value="com.phonegap.Capture"/>
|
||||
</plugins>
|
||||
8
bin/test
@@ -13,14 +13,14 @@ then
|
||||
fi
|
||||
|
||||
# generate a working proj
|
||||
./bin/create ./test com.phonegap.test PhoneGapTest
|
||||
./bin/create ./test org.apache.cordova.test CordovaTest
|
||||
|
||||
# kill the default app and replace it w/ mobile-spec
|
||||
rm -rf ./test/assets/www
|
||||
mv ./callback-test ./test/assets/www
|
||||
|
||||
# copy in phonegap.js since www dir was replaced above
|
||||
cp ./framework/assets/www/phonegap-$VERSION.js ./test/assets/www/phonegap-$VERSION.js
|
||||
# copy in cordova.js since www dir was replaced above
|
||||
cp ./framework/assets/www/cordova-$VERSION.js ./test/assets/www/cordova-$VERSION.js
|
||||
|
||||
# build it, launch it and start logging on stdout
|
||||
cd ./test && ./phonegap/debug && ./phonegap/log
|
||||
cd ./test && ./cordova/debug && ./cordova/log
|
||||
|
||||
@@ -8,14 +8,14 @@ exports['default example project is generated'] = (test) ->
|
||||
test.ok true, "this assertion should pass" unless error?
|
||||
test.done()
|
||||
|
||||
exports['default example project has a ./.phonegap folder'] = (test) ->
|
||||
exports['default example project has a ./.cordova folder'] = (test) ->
|
||||
test.expect 1
|
||||
path.exists './example/.phonegap', (exists) ->
|
||||
test.ok exists, 'the phonegap folder exists'
|
||||
path.exists './example/.cordova', (exists) ->
|
||||
test.ok exists, 'the cordova folder exists'
|
||||
test.done()
|
||||
|
||||
exports['default example project has a /phonegap folder'] = (test) ->
|
||||
exports['default example project has a /cordova folder'] = (test) ->
|
||||
test.expect 1
|
||||
path.exists './example/phonegap', (exists) ->
|
||||
test.ok exists, 'the other phonegap folder exists'
|
||||
path.exists './example/cordova', (exists) ->
|
||||
test.ok exists, 'the other cordova folder exists'
|
||||
test.done()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>PhoneGap</name>
|
||||
<name>Cordova</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
||||
23
framework/AndroidManifest.xml
Normal file → Executable file
@@ -1,6 +1,24 @@
|
||||
<?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="com.phonegap" android:versionName="1.1" android:versionCode="5">
|
||||
package="org.apache.cordova" android:versionName="1.1" android:versionCode="5">
|
||||
<supports-screens
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
@@ -15,6 +33,7 @@
|
||||
<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"/>
|
||||
@@ -38,7 +57,7 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name"
|
||||
<activity android:name="org.apache.cordova.DroidGap" android:label="@string/app_name"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<intent-filter>
|
||||
</intent-filter>
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
# 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
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("accelerometer")) {
|
||||
PhoneGap.addResource("accelerometer");
|
||||
|
||||
/** @constructor */
|
||||
var Acceleration = function(x, y, z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.timestamp = new Date().getTime();
|
||||
};
|
||||
|
||||
/**
|
||||
* This class provides access to device accelerometer data.
|
||||
* @constructor
|
||||
*/
|
||||
var Accelerometer = function() {
|
||||
|
||||
/**
|
||||
* The last known acceleration. type=Acceleration()
|
||||
*/
|
||||
this.lastAcceleration = null;
|
||||
|
||||
/**
|
||||
* List of accelerometer watch timers
|
||||
*/
|
||||
this.timers = {};
|
||||
};
|
||||
|
||||
Accelerometer.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"];
|
||||
|
||||
/**
|
||||
* Asynchronously aquires the current acceleration.
|
||||
*
|
||||
* @param {Function} successCallback The function to call when the acceleration data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
|
||||
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
|
||||
*/
|
||||
Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) {
|
||||
|
||||
// successCallback required
|
||||
if (typeof successCallback !== "function") {
|
||||
console.log("Accelerometer Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Accelerometer Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get acceleration
|
||||
PhoneGap.exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronously aquires the acceleration repeatedly at a given interval.
|
||||
*
|
||||
* @param {Function} successCallback The function to call each time the acceleration data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL)
|
||||
* @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL)
|
||||
* @return String The watch id that must be passed to #clearWatch to stop watching.
|
||||
*/
|
||||
Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) {
|
||||
|
||||
// Default interval (10 sec)
|
||||
var frequency = (options !== undefined)? options.frequency : 10000;
|
||||
|
||||
// successCallback required
|
||||
if (typeof successCallback !== "function") {
|
||||
console.log("Accelerometer Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Accelerometer Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure accelerometer timeout > frequency + 10 sec
|
||||
PhoneGap.exec(
|
||||
function(timeout) {
|
||||
if (timeout < (frequency + 10000)) {
|
||||
PhoneGap.exec(null, null, "Accelerometer", "setTimeout", [frequency + 10000]);
|
||||
}
|
||||
},
|
||||
function(e) { }, "Accelerometer", "getTimeout", []);
|
||||
|
||||
// Start watch timer
|
||||
var id = PhoneGap.createUUID();
|
||||
navigator.accelerometer.timers[id] = setInterval(function() {
|
||||
PhoneGap.exec(successCallback, errorCallback, "Accelerometer", "getAcceleration", []);
|
||||
}, (frequency ? frequency : 1));
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the specified accelerometer watch.
|
||||
*
|
||||
* @param {String} id The id of the watch returned from #watchAcceleration.
|
||||
*/
|
||||
Accelerometer.prototype.clearWatch = function(id) {
|
||||
|
||||
// Stop javascript timer & remove from timer list
|
||||
if (id && navigator.accelerometer.timers[id] !== undefined) {
|
||||
clearInterval(navigator.accelerometer.timers[id]);
|
||||
delete navigator.accelerometer.timers[id];
|
||||
}
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.accelerometer === "undefined") {
|
||||
navigator.accelerometer = new Accelerometer();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("app")) {
|
||||
PhoneGap.addResource("app");
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @constructor
|
||||
*/
|
||||
var App = function() {};
|
||||
|
||||
/**
|
||||
* Clear the resource cache.
|
||||
*/
|
||||
App.prototype.clearCache = function() {
|
||||
PhoneGap.exec(null, null, "App", "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});
|
||||
*/
|
||||
App.prototype.loadUrl = function(url, props) {
|
||||
PhoneGap.exec(null, null, "App", "loadUrl", [url, props]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel loadUrl that is waiting to be loaded.
|
||||
*/
|
||||
App.prototype.cancelLoadUrl = function() {
|
||||
PhoneGap.exec(null, null, "App", "cancelLoadUrl", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear web history in this web view.
|
||||
* Instead of BACK button loading the previous web page, it will exit the app.
|
||||
*/
|
||||
App.prototype.clearHistory = function() {
|
||||
PhoneGap.exec(null, null, "App", "clearHistory", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Go to previous page displayed.
|
||||
* This is the same as pressing the backbutton on Android device.
|
||||
*/
|
||||
App.prototype.backHistory = function() {
|
||||
PhoneGap.exec(null, null, "App", "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
|
||||
*/
|
||||
App.prototype.overrideBackbutton = function(override) {
|
||||
PhoneGap.exec(null, null, "App", "overrideBackbutton", [override]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Exit and terminate the application.
|
||||
*/
|
||||
App.prototype.exitApp = function() {
|
||||
return PhoneGap.exec(null, null, "App", "exitApp", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add entry to approved list of URLs (whitelist) that will be loaded into PhoneGap container instead of default browser.
|
||||
*
|
||||
* @param origin URL regular expression to allow
|
||||
* @param subdomains T=include all subdomains under origin
|
||||
*/
|
||||
App.prototype.addWhiteListEntry = function(origin, subdomains) {
|
||||
return PhoneGap.exec(null, null, "App", "addWhiteListEntry", [origin, subdomains]);
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
navigator.app = new App();
|
||||
});
|
||||
}());
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("battery")) {
|
||||
PhoneGap.addResource("battery");
|
||||
|
||||
/**
|
||||
* This class contains information about the current battery status.
|
||||
* @constructor
|
||||
*/
|
||||
var Battery = function() {
|
||||
this._level = null;
|
||||
this._isPlugged = null;
|
||||
this._batteryListener = [];
|
||||
this._lowListener = [];
|
||||
this._criticalListener = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers as an event producer for battery events.
|
||||
*
|
||||
* @param {Object} eventType
|
||||
* @param {Object} handler
|
||||
* @param {Object} add
|
||||
*/
|
||||
Battery.prototype.eventHandler = function(eventType, handler, add) {
|
||||
var me = navigator.battery;
|
||||
if (add) {
|
||||
// If there are no current registered event listeners start the battery listener on native side.
|
||||
if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) {
|
||||
PhoneGap.exec(me._status, me._error, "Battery", "start", []);
|
||||
}
|
||||
|
||||
// Register the event listener in the proper array
|
||||
if (eventType === "batterystatus") {
|
||||
var pos = me._batteryListener.indexOf(handler);
|
||||
if (pos === -1) {
|
||||
me._batteryListener.push(handler);
|
||||
}
|
||||
} else if (eventType === "batterylow") {
|
||||
var pos = me._lowListener.indexOf(handler);
|
||||
if (pos === -1) {
|
||||
me._lowListener.push(handler);
|
||||
}
|
||||
} else if (eventType === "batterycritical") {
|
||||
var pos = me._criticalListener.indexOf(handler);
|
||||
if (pos === -1) {
|
||||
me._criticalListener.push(handler);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Remove the event listener from the proper array
|
||||
if (eventType === "batterystatus") {
|
||||
var pos = me._batteryListener.indexOf(handler);
|
||||
if (pos > -1) {
|
||||
me._batteryListener.splice(pos, 1);
|
||||
}
|
||||
} else if (eventType === "batterylow") {
|
||||
var pos = me._lowListener.indexOf(handler);
|
||||
if (pos > -1) {
|
||||
me._lowListener.splice(pos, 1);
|
||||
}
|
||||
} else if (eventType === "batterycritical") {
|
||||
var pos = me._criticalListener.indexOf(handler);
|
||||
if (pos > -1) {
|
||||
me._criticalListener.splice(pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no more registered event listeners stop the battery listener on native side.
|
||||
if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) {
|
||||
PhoneGap.exec(null, null, "Battery", "stop", []);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for battery status
|
||||
*
|
||||
* @param {Object} info keys: level, isPlugged
|
||||
*/
|
||||
Battery.prototype._status = function(info) {
|
||||
if (info) {
|
||||
var me = this;
|
||||
if (me._level != info.level || me._isPlugged != info.isPlugged) {
|
||||
// Fire batterystatus event
|
||||
PhoneGap.fireWindowEvent("batterystatus", info);
|
||||
|
||||
// Fire low battery event
|
||||
if (info.level == 20 || info.level == 5) {
|
||||
if (info.level == 20) {
|
||||
PhoneGap.fireWindowEvent("batterylow", info);
|
||||
}
|
||||
else {
|
||||
PhoneGap.fireWindowEvent("batterycritical", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
me._level = info.level;
|
||||
me._isPlugged = info.isPlugged;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Error callback for battery start
|
||||
*/
|
||||
Battery.prototype._error = function(e) {
|
||||
console.log("Error initializing Battery: " + e);
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.battery === "undefined") {
|
||||
navigator.battery = new Battery();
|
||||
PhoneGap.addWindowEventHandler("batterystatus", navigator.battery.eventHandler);
|
||||
PhoneGap.addWindowEventHandler("batterylow", navigator.battery.eventHandler);
|
||||
PhoneGap.addWindowEventHandler("batterycritical", navigator.battery.eventHandler);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("camera")) {
|
||||
PhoneGap.addResource("camera");
|
||||
|
||||
/**
|
||||
* This class provides access to the device camera.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
var Camera = function() {
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
this.options = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Format of image that returned from getPicture.
|
||||
*
|
||||
* Example: navigator.camera.getPicture(success, fail,
|
||||
* { quality: 80,
|
||||
* destinationType: Camera.DestinationType.DATA_URL,
|
||||
* sourceType: Camera.PictureSourceType.PHOTOLIBRARY})
|
||||
*/
|
||||
Camera.DestinationType = {
|
||||
DATA_URL: 0, // Return base64 encoded string
|
||||
FILE_URI: 1 // Return file uri (content://media/external/images/media/2 for Android)
|
||||
};
|
||||
Camera.prototype.DestinationType = Camera.DestinationType;
|
||||
|
||||
/**
|
||||
* Encoding of image returned from getPicture.
|
||||
*
|
||||
* Example: navigator.camera.getPicture(success, fail,
|
||||
* { quality: 80,
|
||||
* destinationType: Camera.DestinationType.DATA_URL,
|
||||
* sourceType: Camera.PictureSourceType.CAMERA,
|
||||
* encodingType: Camera.EncodingType.PNG})
|
||||
*/
|
||||
Camera.EncodingType = {
|
||||
JPEG: 0, // Return JPEG encoded image
|
||||
PNG: 1 // Return PNG encoded image
|
||||
};
|
||||
Camera.prototype.EncodingType = Camera.EncodingType;
|
||||
|
||||
/**
|
||||
* Type of pictures to select from. Only applicable when
|
||||
* PictureSourceType is PHOTOLIBRARY or SAVEDPHOTOALBUM
|
||||
*
|
||||
* Example: navigator.camera.getPicture(success, fail,
|
||||
* { quality: 80,
|
||||
* destinationType: Camera.DestinationType.DATA_URL,
|
||||
* sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
|
||||
* mediaType: Camera.MediaType.PICTURE})
|
||||
*/
|
||||
Camera.MediaType = {
|
||||
PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
|
||||
VIDEO: 1, // allow selection of video only, ONLY RETURNS URL
|
||||
ALLMEDIA : 2 // allow selection from all media types
|
||||
};
|
||||
Camera.prototype.MediaType = Camera.MediaType;
|
||||
|
||||
|
||||
/**
|
||||
* Source to getPicture from.
|
||||
*
|
||||
* Example: navigator.camera.getPicture(success, fail,
|
||||
* { quality: 80,
|
||||
* destinationType: Camera.DestinationType.DATA_URL,
|
||||
* sourceType: Camera.PictureSourceType.PHOTOLIBRARY})
|
||||
*/
|
||||
Camera.PictureSourceType = {
|
||||
PHOTOLIBRARY : 0, // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
|
||||
CAMERA : 1, // Take picture from camera
|
||||
SAVEDPHOTOALBUM : 2 // Choose image from picture library (same as PHOTOLIBRARY for Android)
|
||||
};
|
||||
Camera.prototype.PictureSourceType = Camera.PictureSourceType;
|
||||
|
||||
/**
|
||||
* Gets a picture from source defined by "options.sourceType", and returns the
|
||||
* image as defined by the "options.destinationType" option.
|
||||
|
||||
* The defaults are sourceType=CAMERA and destinationType=DATA_URL.
|
||||
*
|
||||
* @param {Function} successCallback
|
||||
* @param {Function} errorCallback
|
||||
* @param {Object} options
|
||||
*/
|
||||
Camera.prototype.getPicture = function(successCallback, errorCallback, options) {
|
||||
|
||||
// successCallback required
|
||||
if (typeof successCallback !== "function") {
|
||||
console.log("Camera Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Camera Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
if (options === null || typeof options === "undefined") {
|
||||
options = {};
|
||||
}
|
||||
if (options.quality === null || typeof options.quality === "undefined") {
|
||||
options.quality = 80;
|
||||
}
|
||||
if (options.maxResolution === null || typeof options.maxResolution === "undefined") {
|
||||
options.maxResolution = 0;
|
||||
}
|
||||
if (options.destinationType === null || typeof options.destinationType === "undefined") {
|
||||
options.destinationType = Camera.DestinationType.DATA_URL;
|
||||
}
|
||||
if (options.sourceType === null || typeof options.sourceType === "undefined") {
|
||||
options.sourceType = Camera.PictureSourceType.CAMERA;
|
||||
}
|
||||
if (options.encodingType === null || typeof options.encodingType === "undefined") {
|
||||
options.encodingType = Camera.EncodingType.JPEG;
|
||||
}
|
||||
if (options.mediaType === null || typeof options.mediaType === "undefined") {
|
||||
options.mediaType = Camera.MediaType.PICTURE;
|
||||
}
|
||||
if (options.targetWidth === null || typeof options.targetWidth === "undefined") {
|
||||
options.targetWidth = -1;
|
||||
}
|
||||
else if (typeof options.targetWidth == "string") {
|
||||
var width = new Number(options.targetWidth);
|
||||
if (isNaN(width) === false) {
|
||||
options.targetWidth = width.valueOf();
|
||||
}
|
||||
}
|
||||
if (options.targetHeight === null || typeof options.targetHeight === "undefined") {
|
||||
options.targetHeight = -1;
|
||||
}
|
||||
else if (typeof options.targetHeight == "string") {
|
||||
var height = new Number(options.targetHeight);
|
||||
if (isNaN(height) === false) {
|
||||
options.targetHeight = height.valueOf();
|
||||
}
|
||||
}
|
||||
|
||||
PhoneGap.exec(successCallback, errorCallback, "Camera", "takePicture", [options]);
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.camera === "undefined") {
|
||||
navigator.camera = new Camera();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("capture")) {
|
||||
PhoneGap.addResource("capture");
|
||||
|
||||
/**
|
||||
* Represents a single file.
|
||||
*
|
||||
* name {DOMString} name of the file, without path information
|
||||
* fullPath {DOMString} the full path of the file, including the name
|
||||
* type {DOMString} mime type
|
||||
* lastModifiedDate {Date} last modified date
|
||||
* size {Number} size of the file in bytes
|
||||
*/
|
||||
var MediaFile = function(name, fullPath, type, lastModifiedDate, size){
|
||||
this.name = name || null;
|
||||
this.fullPath = fullPath || null;
|
||||
this.type = type || null;
|
||||
this.lastModifiedDate = lastModifiedDate || null;
|
||||
this.size = size || 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch device camera application for recording video(s).
|
||||
*
|
||||
* @param {Function} successCB
|
||||
* @param {Function} errorCB
|
||||
*/
|
||||
MediaFile.prototype.getFormatData = function(successCallback, errorCallback){
|
||||
PhoneGap.exec(successCallback, errorCallback, "Capture", "getFormatData", [this.fullPath, this.type]);
|
||||
};
|
||||
|
||||
/**
|
||||
* MediaFileData encapsulates format information of a media file.
|
||||
*
|
||||
* @param {DOMString} codecs
|
||||
* @param {long} bitrate
|
||||
* @param {long} height
|
||||
* @param {long} width
|
||||
* @param {float} duration
|
||||
*/
|
||||
var MediaFileData = function(codecs, bitrate, height, width, duration){
|
||||
this.codecs = codecs || null;
|
||||
this.bitrate = bitrate || 0;
|
||||
this.height = height || 0;
|
||||
this.width = width || 0;
|
||||
this.duration = duration || 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* The CaptureError interface encapsulates all errors in the Capture API.
|
||||
*/
|
||||
var CaptureError = function(){
|
||||
this.code = null;
|
||||
};
|
||||
|
||||
// Capture error codes
|
||||
CaptureError.CAPTURE_INTERNAL_ERR = 0;
|
||||
CaptureError.CAPTURE_APPLICATION_BUSY = 1;
|
||||
CaptureError.CAPTURE_INVALID_ARGUMENT = 2;
|
||||
CaptureError.CAPTURE_NO_MEDIA_FILES = 3;
|
||||
CaptureError.CAPTURE_NOT_SUPPORTED = 20;
|
||||
|
||||
/**
|
||||
* The Capture interface exposes an interface to the camera and microphone of the hosting device.
|
||||
*/
|
||||
var Capture = function(){
|
||||
this.supportedAudioModes = [];
|
||||
this.supportedImageModes = [];
|
||||
this.supportedVideoModes = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch audio recorder application for recording audio clip(s).
|
||||
*
|
||||
* @param {Function} successCB
|
||||
* @param {Function} errorCB
|
||||
* @param {CaptureAudioOptions} options
|
||||
*/
|
||||
Capture.prototype.captureAudio = function(successCallback, errorCallback, options){
|
||||
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureAudio", [options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch camera application for taking image(s).
|
||||
*
|
||||
* @param {Function} successCB
|
||||
* @param {Function} errorCB
|
||||
* @param {CaptureImageOptions} options
|
||||
*/
|
||||
Capture.prototype.captureImage = function(successCallback, errorCallback, options){
|
||||
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureImage", [options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch camera application for taking image(s).
|
||||
*
|
||||
* @param {Function} successCB
|
||||
* @param {Function} errorCB
|
||||
* @param {CaptureImageOptions} options
|
||||
*/
|
||||
Capture.prototype._castMediaFile = function(pluginResult){
|
||||
var mediaFiles = [];
|
||||
var i;
|
||||
for (i = 0; i < pluginResult.message.length; i++) {
|
||||
var mediaFile = new MediaFile();
|
||||
mediaFile.name = pluginResult.message[i].name;
|
||||
mediaFile.fullPath = pluginResult.message[i].fullPath;
|
||||
mediaFile.type = pluginResult.message[i].type;
|
||||
mediaFile.lastModifiedDate = pluginResult.message[i].lastModifiedDate;
|
||||
mediaFile.size = pluginResult.message[i].size;
|
||||
mediaFiles.push(mediaFile);
|
||||
}
|
||||
pluginResult.message = mediaFiles;
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch device camera application for recording video(s).
|
||||
*
|
||||
* @param {Function} successCB
|
||||
* @param {Function} errorCB
|
||||
* @param {CaptureVideoOptions} options
|
||||
*/
|
||||
Capture.prototype.captureVideo = function(successCallback, errorCallback, options){
|
||||
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureVideo", [options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulates a set of parameters that the capture device supports.
|
||||
*/
|
||||
var ConfigurationData = function(){
|
||||
// The ASCII-encoded string in lower case representing the media type.
|
||||
this.type = null;
|
||||
// The height attribute represents height of the image or video in pixels.
|
||||
// In the case of a sound clip this attribute has value 0.
|
||||
this.height = 0;
|
||||
// The width attribute represents width of the image or video in pixels.
|
||||
// In the case of a sound clip this attribute has value 0
|
||||
this.width = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulates all image capture operation configuration options.
|
||||
*/
|
||||
var CaptureImageOptions = function(){
|
||||
// Upper limit of images user can take. Value must be equal or greater than 1.
|
||||
this.limit = 1;
|
||||
// The selected image mode. Must match with one of the elements in supportedImageModes array.
|
||||
this.mode = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulates all video capture operation configuration options.
|
||||
*/
|
||||
var CaptureVideoOptions = function(){
|
||||
// Upper limit of videos user can record. Value must be equal or greater than 1.
|
||||
this.limit = 1;
|
||||
// Maximum duration of a single video clip in seconds.
|
||||
this.duration = 0;
|
||||
// The selected video mode. Must match with one of the elements in supportedVideoModes array.
|
||||
this.mode = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulates all audio capture operation configuration options.
|
||||
*/
|
||||
var CaptureAudioOptions = function(){
|
||||
// Upper limit of sound clips user can record. Value must be equal or greater than 1.
|
||||
this.limit = 1;
|
||||
// Maximum duration of a single sound clip in seconds.
|
||||
this.duration = 0;
|
||||
// The selected audio mode. Must match with one of the elements in supportedAudioModes array.
|
||||
this.mode = null;
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function(){
|
||||
if (typeof navigator.device === "undefined") {
|
||||
navigator.device = window.device = new Device();
|
||||
}
|
||||
if (typeof navigator.device.capture === "undefined") {
|
||||
navigator.device.capture = window.device.capture = new Capture();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("compass")) {
|
||||
PhoneGap.addResource("compass");
|
||||
|
||||
CompassError = function(){
|
||||
this.code = null;
|
||||
};
|
||||
|
||||
// Capture error codes
|
||||
CompassError.COMPASS_INTERNAL_ERR = 0;
|
||||
CompassError.COMPASS_NOT_SUPPORTED = 20;
|
||||
|
||||
CompassHeading = function() {
|
||||
this.magneticHeading = null;
|
||||
this.trueHeading = null;
|
||||
this.headingAccuracy = null;
|
||||
this.timestamp = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class provides access to device Compass data.
|
||||
* @constructor
|
||||
*/
|
||||
var Compass = function() {
|
||||
/**
|
||||
* The last known Compass position.
|
||||
*/
|
||||
this.lastHeading = null;
|
||||
|
||||
/**
|
||||
* List of compass watch timers
|
||||
*/
|
||||
this.timers = {};
|
||||
};
|
||||
|
||||
Compass.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"];
|
||||
|
||||
/**
|
||||
* Asynchronously aquires the current heading.
|
||||
*
|
||||
* @param {Function} successCallback The function to call when the heading data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
|
||||
* @param {PositionOptions} options The options for getting the heading data such as timeout. (OPTIONAL)
|
||||
*/
|
||||
Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, options) {
|
||||
|
||||
// successCallback required
|
||||
if (typeof successCallback !== "function") {
|
||||
console.log("Compass Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Compass Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get heading
|
||||
PhoneGap.exec(successCallback, errorCallback, "Compass", "getHeading", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronously aquires the heading repeatedly at a given interval.
|
||||
*
|
||||
* @param {Function} successCallback The function to call each time the heading data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
|
||||
* @param {HeadingOptions} options The options for getting the heading data such as timeout and the frequency of the watch. (OPTIONAL)
|
||||
* @return String The watch id that must be passed to #clearWatch to stop watching.
|
||||
*/
|
||||
Compass.prototype.watchHeading= function(successCallback, errorCallback, options) {
|
||||
|
||||
// Default interval (100 msec)
|
||||
var frequency = (options !== undefined) ? options.frequency : 100;
|
||||
|
||||
// successCallback required
|
||||
if (typeof successCallback !== "function") {
|
||||
console.log("Compass Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Compass Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure compass timeout > frequency + 10 sec
|
||||
PhoneGap.exec(
|
||||
function(timeout) {
|
||||
if (timeout < (frequency + 10000)) {
|
||||
PhoneGap.exec(null, null, "Compass", "setTimeout", [frequency + 10000]);
|
||||
}
|
||||
},
|
||||
function(e) { }, "Compass", "getTimeout", []);
|
||||
|
||||
// Start watch timer to get headings
|
||||
var id = PhoneGap.createUUID();
|
||||
navigator.compass.timers[id] = setInterval(
|
||||
function() {
|
||||
PhoneGap.exec(successCallback, errorCallback, "Compass", "getHeading", []);
|
||||
}, (frequency ? frequency : 1));
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clears the specified heading watch.
|
||||
*
|
||||
* @param {String} id The ID of the watch returned from #watchHeading.
|
||||
*/
|
||||
Compass.prototype.clearWatch = function(id) {
|
||||
|
||||
// Stop javascript timer & remove from timer list
|
||||
if (id && navigator.compass.timers[id]) {
|
||||
clearInterval(navigator.compass.timers[id]);
|
||||
delete navigator.compass.timers[id];
|
||||
}
|
||||
};
|
||||
|
||||
Compass.prototype._castDate = function(pluginResult) {
|
||||
if (pluginResult.message.timestamp) {
|
||||
var timestamp = new Date(pluginResult.message.timestamp);
|
||||
pluginResult.message.timestamp = timestamp;
|
||||
}
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.compass === "undefined") {
|
||||
navigator.compass = new Compass();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("contact")) {
|
||||
PhoneGap.addResource("contact");
|
||||
|
||||
/**
|
||||
* Contains information about a single contact.
|
||||
* @constructor
|
||||
* @param {DOMString} id unique identifier
|
||||
* @param {DOMString} displayName
|
||||
* @param {ContactName} name
|
||||
* @param {DOMString} nickname
|
||||
* @param {Array.<ContactField>} phoneNumbers array of phone numbers
|
||||
* @param {Array.<ContactField>} emails array of email addresses
|
||||
* @param {Array.<ContactAddress>} addresses array of addresses
|
||||
* @param {Array.<ContactField>} ims instant messaging user ids
|
||||
* @param {Array.<ContactOrganization>} organizations
|
||||
* @param {DOMString} birthday contact's birthday
|
||||
* @param {DOMString} note user notes about contact
|
||||
* @param {Array.<ContactField>} photos
|
||||
* @param {Array.<ContactField>} categories
|
||||
* @param {Array.<ContactField>} urls contact's web sites
|
||||
*/
|
||||
var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses,
|
||||
ims, organizations, birthday, note, photos, categories, urls) {
|
||||
this.id = id || null;
|
||||
this.rawId = null;
|
||||
this.displayName = displayName || null;
|
||||
this.name = name || null; // ContactName
|
||||
this.nickname = nickname || null;
|
||||
this.phoneNumbers = phoneNumbers || null; // ContactField[]
|
||||
this.emails = emails || null; // ContactField[]
|
||||
this.addresses = addresses || null; // ContactAddress[]
|
||||
this.ims = ims || null; // ContactField[]
|
||||
this.organizations = organizations || null; // ContactOrganization[]
|
||||
this.birthday = birthday || null;
|
||||
this.note = note || null;
|
||||
this.photos = photos || null; // ContactField[]
|
||||
this.categories = categories || null; // ContactField[]
|
||||
this.urls = urls || null; // ContactField[]
|
||||
};
|
||||
|
||||
/**
|
||||
* ContactError.
|
||||
* An error code assigned by an implementation when an error has occurreds
|
||||
* @constructor
|
||||
*/
|
||||
var ContactError = function() {
|
||||
this.code=null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
*/
|
||||
ContactError.UNKNOWN_ERROR = 0;
|
||||
ContactError.INVALID_ARGUMENT_ERROR = 1;
|
||||
ContactError.TIMEOUT_ERROR = 2;
|
||||
ContactError.PENDING_OPERATION_ERROR = 3;
|
||||
ContactError.IO_ERROR = 4;
|
||||
ContactError.NOT_SUPPORTED_ERROR = 5;
|
||||
ContactError.PERMISSION_DENIED_ERROR = 20;
|
||||
|
||||
/**
|
||||
* Removes contact from device storage.
|
||||
* @param successCB success callback
|
||||
* @param errorCB error callback
|
||||
*/
|
||||
Contact.prototype.remove = function(successCB, errorCB) {
|
||||
if (this.id === null) {
|
||||
var errorObj = new ContactError();
|
||||
errorObj.code = ContactError.UNKNOWN_ERROR;
|
||||
errorCB(errorObj);
|
||||
}
|
||||
else {
|
||||
PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a deep copy of this Contact.
|
||||
* With the contact ID set to null.
|
||||
* @return copy of this Contact
|
||||
*/
|
||||
Contact.prototype.clone = function() {
|
||||
var clonedContact = PhoneGap.clone(this);
|
||||
var i;
|
||||
clonedContact.id = null;
|
||||
clonedContact.rawId = null;
|
||||
// Loop through and clear out any id's in phones, emails, etc.
|
||||
if (clonedContact.phoneNumbers) {
|
||||
for (i = 0; i < clonedContact.phoneNumbers.length; i++) {
|
||||
clonedContact.phoneNumbers[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.emails) {
|
||||
for (i = 0; i < clonedContact.emails.length; i++) {
|
||||
clonedContact.emails[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.addresses) {
|
||||
for (i = 0; i < clonedContact.addresses.length; i++) {
|
||||
clonedContact.addresses[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.ims) {
|
||||
for (i = 0; i < clonedContact.ims.length; i++) {
|
||||
clonedContact.ims[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.organizations) {
|
||||
for (i = 0; i < clonedContact.organizations.length; i++) {
|
||||
clonedContact.organizations[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.tags) {
|
||||
for (i = 0; i < clonedContact.tags.length; i++) {
|
||||
clonedContact.tags[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.photos) {
|
||||
for (i = 0; i < clonedContact.photos.length; i++) {
|
||||
clonedContact.photos[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.urls) {
|
||||
for (i = 0; i < clonedContact.urls.length; i++) {
|
||||
clonedContact.urls[i].id = null;
|
||||
}
|
||||
}
|
||||
return clonedContact;
|
||||
};
|
||||
|
||||
/**
|
||||
* Persists contact to device storage.
|
||||
* @param successCB success callback
|
||||
* @param errorCB error callback
|
||||
*/
|
||||
Contact.prototype.save = function(successCB, errorCB) {
|
||||
PhoneGap.exec(successCB, errorCB, "Contacts", "save", [this]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Contact name.
|
||||
* @constructor
|
||||
* @param formatted
|
||||
* @param familyName
|
||||
* @param givenName
|
||||
* @param middle
|
||||
* @param prefix
|
||||
* @param suffix
|
||||
*/
|
||||
var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) {
|
||||
this.formatted = formatted || null;
|
||||
this.familyName = familyName || null;
|
||||
this.givenName = givenName || null;
|
||||
this.middleName = middle || null;
|
||||
this.honorificPrefix = prefix || null;
|
||||
this.honorificSuffix = suffix || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic contact field.
|
||||
* @constructor
|
||||
* @param {DOMString} id unique identifier, should only be set by native code
|
||||
* @param type
|
||||
* @param value
|
||||
* @param pref
|
||||
*/
|
||||
var ContactField = function(type, value, pref) {
|
||||
this.id = null;
|
||||
this.type = type || null;
|
||||
this.value = value || null;
|
||||
this.pref = pref || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contact address.
|
||||
* @constructor
|
||||
* @param {DOMString} id unique identifier, should only be set by native code
|
||||
* @param formatted
|
||||
* @param streetAddress
|
||||
* @param locality
|
||||
* @param region
|
||||
* @param postalCode
|
||||
* @param country
|
||||
*/
|
||||
var ContactAddress = function(pref, type, formatted, streetAddress, locality, region, postalCode, country) {
|
||||
this.id = null;
|
||||
this.pref = pref || null;
|
||||
this.type = type || null;
|
||||
this.formatted = formatted || null;
|
||||
this.streetAddress = streetAddress || null;
|
||||
this.locality = locality || null;
|
||||
this.region = region || null;
|
||||
this.postalCode = postalCode || null;
|
||||
this.country = country || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contact organization.
|
||||
* @constructor
|
||||
* @param {DOMString} id unique identifier, should only be set by native code
|
||||
* @param name
|
||||
* @param dept
|
||||
* @param title
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @param location
|
||||
* @param desc
|
||||
*/
|
||||
var ContactOrganization = function(pref, type, name, dept, title) {
|
||||
this.id = null;
|
||||
this.pref = pref || null;
|
||||
this.type = type || null;
|
||||
this.name = name || null;
|
||||
this.department = dept || null;
|
||||
this.title = title || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a group of Contacts.
|
||||
* @constructor
|
||||
*/
|
||||
var Contacts = function() {
|
||||
this.inProgress = false;
|
||||
this.records = [];
|
||||
};
|
||||
/**
|
||||
* Returns an array of Contacts matching the search criteria.
|
||||
* @param fields that should be searched
|
||||
* @param successCB success callback
|
||||
* @param errorCB error callback
|
||||
* @param {ContactFindOptions} options that can be applied to contact searching
|
||||
* @return array of Contacts matching search criteria
|
||||
*/
|
||||
Contacts.prototype.find = function(fields, successCB, errorCB, options) {
|
||||
if (successCB === null) {
|
||||
throw new TypeError("You must specify a success callback for the find command.");
|
||||
}
|
||||
if (fields === null || fields === "undefined" || fields.length === "undefined" || fields.length <= 0) {
|
||||
if (typeof errorCB === "function") {
|
||||
errorCB({"code": ContactError.INVALID_ARGUMENT_ERROR});
|
||||
}
|
||||
} else {
|
||||
PhoneGap.exec(successCB, errorCB, "Contacts", "search", [fields, options]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This function creates a new contact, but it does not persist the contact
|
||||
* to device storage. To persist the contact to device storage, invoke
|
||||
* contact.save().
|
||||
* @param properties an object who's properties will be examined to create a new Contact
|
||||
* @returns new Contact object
|
||||
*/
|
||||
Contacts.prototype.create = function(properties) {
|
||||
var i;
|
||||
var contact = new Contact();
|
||||
for (i in properties) {
|
||||
if (contact[i] !== 'undefined') {
|
||||
contact[i] = properties[i];
|
||||
}
|
||||
}
|
||||
return contact;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function returns and array of contacts. It is required as we need to convert raw
|
||||
* JSON objects into concrete Contact objects. Currently this method is called after
|
||||
* navigator.contacts.find but before the find methods success call back.
|
||||
*
|
||||
* @param jsonArray an array of JSON Objects that need to be converted to Contact objects.
|
||||
* @returns an array of Contact objects
|
||||
*/
|
||||
Contacts.prototype.cast = function(pluginResult) {
|
||||
var contacts = [];
|
||||
var i;
|
||||
for (i=0; i<pluginResult.message.length; i++) {
|
||||
contacts.push(navigator.contacts.create(pluginResult.message[i]));
|
||||
}
|
||||
pluginResult.message = contacts;
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* ContactFindOptions.
|
||||
* @constructor
|
||||
* @param filter used to match contacts against
|
||||
* @param multiple boolean used to determine if more than one contact should be returned
|
||||
*/
|
||||
var ContactFindOptions = function(filter, multiple) {
|
||||
this.filter = filter || '';
|
||||
this.multiple = multiple || false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the contact interface into the browser.
|
||||
*/
|
||||
PhoneGap.addConstructor(function() {
|
||||
if(typeof navigator.contacts === "undefined") {
|
||||
navigator.contacts = new Contacts();
|
||||
}
|
||||
});
|
||||
}
|
||||
4856
framework/assets/js/cordova.android.js
Normal file
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
// TODO: Needs to be commented
|
||||
|
||||
if (!PhoneGap.hasResource("crypto")) {
|
||||
PhoneGap.addResource("crypto");
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
var Crypto = function() {
|
||||
};
|
||||
|
||||
Crypto.prototype.encrypt = function(seed, string, callback) {
|
||||
this.encryptWin = callback;
|
||||
PhoneGap.exec(null, null, "Crypto", "encrypt", [seed, string]);
|
||||
};
|
||||
|
||||
Crypto.prototype.decrypt = function(seed, string, callback) {
|
||||
this.decryptWin = callback;
|
||||
PhoneGap.exec(null, null, "Crypto", "decrypt", [seed, string]);
|
||||
};
|
||||
|
||||
Crypto.prototype.gotCryptedString = function(string) {
|
||||
this.encryptWin(string);
|
||||
};
|
||||
|
||||
Crypto.prototype.getPlainString = function(string) {
|
||||
this.decryptWin(string);
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.Crypto === "undefined") {
|
||||
navigator.Crypto = new Crypto();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("device")) {
|
||||
PhoneGap.addResource("device");
|
||||
|
||||
/**
|
||||
* This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
|
||||
* phone, etc.
|
||||
* @constructor
|
||||
*/
|
||||
var Device = function() {
|
||||
this.available = PhoneGap.available;
|
||||
this.platform = null;
|
||||
this.version = null;
|
||||
this.name = null;
|
||||
this.uuid = null;
|
||||
this.phonegap = null;
|
||||
|
||||
var me = this;
|
||||
this.getInfo(
|
||||
function(info) {
|
||||
me.available = true;
|
||||
me.platform = info.platform;
|
||||
me.version = info.version;
|
||||
me.name = info.name;
|
||||
me.uuid = info.uuid;
|
||||
me.phonegap = info.phonegap;
|
||||
PhoneGap.onPhoneGapInfoReady.fire();
|
||||
},
|
||||
function(e) {
|
||||
me.available = false;
|
||||
console.log("Error initializing PhoneGap: " + e);
|
||||
alert("Error initializing PhoneGap: "+e);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get device info
|
||||
*
|
||||
* @param {Function} successCallback The function to call when the heading data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
|
||||
*/
|
||||
Device.prototype.getInfo = function(successCallback, errorCallback) {
|
||||
|
||||
// successCallback required
|
||||
if (typeof successCallback !== "function") {
|
||||
console.log("Device Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Device Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get info
|
||||
PhoneGap.exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
|
||||
};
|
||||
|
||||
/*
|
||||
* DEPRECATED
|
||||
* This is only for Android.
|
||||
*
|
||||
* You must explicitly override the back button.
|
||||
*/
|
||||
Device.prototype.overrideBackButton = function() {
|
||||
console.log("Device.overrideBackButton() is deprecated. Use App.overrideBackbutton(true).");
|
||||
navigator.app.overrideBackbutton(true);
|
||||
};
|
||||
|
||||
/*
|
||||
* DEPRECATED
|
||||
* This is only for Android.
|
||||
*
|
||||
* This resets the back button to the default behaviour
|
||||
*/
|
||||
Device.prototype.resetBackButton = function() {
|
||||
console.log("Device.resetBackButton() is deprecated. Use App.overrideBackbutton(false).");
|
||||
navigator.app.overrideBackbutton(false);
|
||||
};
|
||||
|
||||
/*
|
||||
* DEPRECATED
|
||||
* This is only for Android.
|
||||
*
|
||||
* This terminates the activity!
|
||||
*/
|
||||
Device.prototype.exitApp = function() {
|
||||
console.log("Device.exitApp() is deprecated. Use App.exitApp().");
|
||||
navigator.app.exitApp();
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.device === "undefined") {
|
||||
navigator.device = window.device = new Device();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,989 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("file")) {
|
||||
PhoneGap.addResource("file");
|
||||
|
||||
/**
|
||||
* This class provides some useful information about a file.
|
||||
* @constructor
|
||||
*/
|
||||
var FileProperties = function(filePath) {
|
||||
this.filePath = filePath;
|
||||
this.size = 0;
|
||||
this.lastModifiedDate = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a single file.
|
||||
*
|
||||
* @constructor
|
||||
* @param name {DOMString} name of the file, without path information
|
||||
* @param fullPath {DOMString} the full path of the file, including the name
|
||||
* @param type {DOMString} mime type
|
||||
* @param lastModifiedDate {Date} last modified date
|
||||
* @param size {Number} size of the file in bytes
|
||||
*/
|
||||
var File = function(name, fullPath, type, lastModifiedDate, size) {
|
||||
this.name = name || null;
|
||||
this.fullPath = fullPath || null;
|
||||
this.type = type || null;
|
||||
this.lastModifiedDate = lastModifiedDate || null;
|
||||
this.size = size || 0;
|
||||
};
|
||||
|
||||
/** @constructor */
|
||||
var FileError = function() {
|
||||
this.code = null;
|
||||
};
|
||||
|
||||
// File error codes
|
||||
// Found in DOMException
|
||||
FileError.NOT_FOUND_ERR = 1;
|
||||
FileError.SECURITY_ERR = 2;
|
||||
FileError.ABORT_ERR = 3;
|
||||
|
||||
// Added by this specification
|
||||
FileError.NOT_READABLE_ERR = 4;
|
||||
FileError.ENCODING_ERR = 5;
|
||||
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
|
||||
FileError.INVALID_STATE_ERR = 7;
|
||||
FileError.SYNTAX_ERR = 8;
|
||||
FileError.INVALID_MODIFICATION_ERR = 9;
|
||||
FileError.QUOTA_EXCEEDED_ERR = 10;
|
||||
FileError.TYPE_MISMATCH_ERR = 11;
|
||||
FileError.PATH_EXISTS_ERR = 12;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File Reader
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This class reads the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To read from the SD card, the file name is "sdcard/my_file.txt"
|
||||
* @constructor
|
||||
*/
|
||||
var FileReader = function() {
|
||||
this.fileName = "";
|
||||
|
||||
this.readyState = 0;
|
||||
|
||||
// File data
|
||||
this.result = null;
|
||||
|
||||
// Error
|
||||
this.error = null;
|
||||
|
||||
// Event handlers
|
||||
this.onloadstart = null; // When the read starts.
|
||||
this.onprogress = null; // While reading (and decoding) file or fileBlob data, and reporting partial file data (progess.loaded/progress.total)
|
||||
this.onload = null; // When the read has successfully completed.
|
||||
this.onerror = null; // When the read has failed (see errors).
|
||||
this.onloadend = null; // When the request has completed (either in success or failure).
|
||||
this.onabort = null; // When the read has been aborted. For instance, by invoking the abort() method.
|
||||
};
|
||||
|
||||
// States
|
||||
FileReader.EMPTY = 0;
|
||||
FileReader.LOADING = 1;
|
||||
FileReader.DONE = 2;
|
||||
|
||||
/**
|
||||
* Abort reading file.
|
||||
*/
|
||||
FileReader.prototype.abort = function() {
|
||||
var evt;
|
||||
this.readyState = FileReader.DONE;
|
||||
this.result = null;
|
||||
|
||||
// set error
|
||||
var error = new FileError();
|
||||
error.code = error.ABORT_ERR;
|
||||
this.error = error;
|
||||
|
||||
// If error callback
|
||||
if (typeof this.onerror === "function") {
|
||||
this.onerror({"type":"error", "target":this});
|
||||
}
|
||||
// If abort callback
|
||||
if (typeof this.onabort === "function") {
|
||||
this.onabort({"type":"abort", "target":this});
|
||||
}
|
||||
// If load end callback
|
||||
if (typeof this.onloadend === "function") {
|
||||
this.onloadend({"type":"loadend", "target":this});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Read text file.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
* @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
|
||||
*/
|
||||
FileReader.prototype.readAsText = function(file, encoding) {
|
||||
this.fileName = "";
|
||||
if (typeof file.fullPath === "undefined") {
|
||||
this.fileName = file;
|
||||
} else {
|
||||
this.fileName = file.fullPath;
|
||||
}
|
||||
|
||||
// LOADING state
|
||||
this.readyState = FileReader.LOADING;
|
||||
|
||||
// If loadstart callback
|
||||
if (typeof this.onloadstart === "function") {
|
||||
this.onloadstart({"type":"loadstart", "target":this});
|
||||
}
|
||||
|
||||
// Default encoding is UTF-8
|
||||
var enc = encoding ? encoding : "UTF-8";
|
||||
|
||||
var me = this;
|
||||
|
||||
// Read file
|
||||
PhoneGap.exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
var evt;
|
||||
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save result
|
||||
me.result = r;
|
||||
|
||||
// If onload callback
|
||||
if (typeof me.onload === "function") {
|
||||
me.onload({"type":"load", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend === "function") {
|
||||
me.onloadend({"type":"loadend", "target":me});
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
var evt;
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror({"type":"error", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend === "function") {
|
||||
me.onloadend({"type":"loadend", "target":me});
|
||||
}
|
||||
}, "File", "readAsText", [this.fileName, enc]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read file and return data as a base64 encoded data url.
|
||||
* A data url is of the form:
|
||||
* data:[<mediatype>][;base64],<data>
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsDataURL = function(file) {
|
||||
this.fileName = "";
|
||||
if (typeof file.fullPath === "undefined") {
|
||||
this.fileName = file;
|
||||
} else {
|
||||
this.fileName = file.fullPath;
|
||||
}
|
||||
|
||||
// LOADING state
|
||||
this.readyState = FileReader.LOADING;
|
||||
|
||||
// If loadstart callback
|
||||
if (typeof this.onloadstart === "function") {
|
||||
this.onloadstart({"type":"loadstart", "target":this});
|
||||
}
|
||||
|
||||
var me = this;
|
||||
|
||||
// Read file
|
||||
PhoneGap.exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
var evt;
|
||||
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save result
|
||||
me.result = r;
|
||||
|
||||
// If onload callback
|
||||
if (typeof me.onload === "function") {
|
||||
me.onload({"type":"load", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend === "function") {
|
||||
me.onloadend({"type":"loadend", "target":me});
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
var evt;
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileReader.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror({"type":"error", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend === "function") {
|
||||
me.onloadend({"type":"loadend", "target":me});
|
||||
}
|
||||
}, "File", "readAsDataURL", [this.fileName]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsBinaryString = function(file) {
|
||||
// TODO - Can't return binary data to browser.
|
||||
this.fileName = file;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read file and return data as a binary data.
|
||||
*
|
||||
* @param file {File} File object containing file properties
|
||||
*/
|
||||
FileReader.prototype.readAsArrayBuffer = function(file) {
|
||||
// TODO - Can't return binary data to browser.
|
||||
this.fileName = file;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File Writer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This class writes to the mobile device file system.
|
||||
*
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To write to the SD card, the file name is "sdcard/my_file.txt"
|
||||
*
|
||||
* @constructor
|
||||
* @param file {File} File object containing file properties
|
||||
* @param append if true write to the end of the file, otherwise overwrite the file
|
||||
*/
|
||||
var FileWriter = function(file) {
|
||||
this.fileName = "";
|
||||
this.length = 0;
|
||||
if (file) {
|
||||
this.fileName = file.fullPath || file;
|
||||
this.length = file.size || 0;
|
||||
}
|
||||
// default is to write at the beginning of the file
|
||||
this.position = 0;
|
||||
|
||||
this.readyState = 0; // EMPTY
|
||||
|
||||
this.result = null;
|
||||
|
||||
// Error
|
||||
this.error = null;
|
||||
|
||||
// Event handlers
|
||||
this.onwritestart = null; // When writing starts
|
||||
this.onprogress = null; // While writing the file, and reporting partial file data
|
||||
this.onwrite = null; // When the write has successfully completed.
|
||||
this.onwriteend = null; // When the request has completed (either in success or failure).
|
||||
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
|
||||
this.onerror = null; // When the write has failed (see errors).
|
||||
};
|
||||
|
||||
// States
|
||||
FileWriter.INIT = 0;
|
||||
FileWriter.WRITING = 1;
|
||||
FileWriter.DONE = 2;
|
||||
|
||||
/**
|
||||
* Abort writing file.
|
||||
*/
|
||||
FileWriter.prototype.abort = function() {
|
||||
// check for invalid state
|
||||
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// set error
|
||||
var error = new FileError(), evt;
|
||||
error.code = error.ABORT_ERR;
|
||||
this.error = error;
|
||||
|
||||
// If error callback
|
||||
if (typeof this.onerror === "function") {
|
||||
this.onerror({"type":"error", "target":this});
|
||||
}
|
||||
// If abort callback
|
||||
if (typeof this.onabort === "function") {
|
||||
this.onabort({"type":"abort", "target":this});
|
||||
}
|
||||
|
||||
this.readyState = FileWriter.DONE;
|
||||
|
||||
// If write end callback
|
||||
if (typeof this.onwriteend == "function") {
|
||||
this.onwriteend({"type":"writeend", "target":this});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes data to the file
|
||||
*
|
||||
* @param text to be written
|
||||
*/
|
||||
FileWriter.prototype.write = function(text) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart({"type":"writestart", "target":me});
|
||||
}
|
||||
|
||||
// Write file
|
||||
PhoneGap.exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
var evt;
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// position always increases by bytes written because file would be extended
|
||||
me.position += r;
|
||||
// The length of the file is now where we are done writing.
|
||||
me.length = me.position;
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite({"type":"write", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend({"type":"writeend", "target":me});
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
var evt;
|
||||
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror({"type":"error", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend({"type":"writeend", "target":me});
|
||||
}
|
||||
}, "File", "write", [this.fileName, text, this.position]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the file pointer to the location specified.
|
||||
*
|
||||
* If the offset is a negative number the position of the file
|
||||
* pointer is rewound. If the offset is greater than the file
|
||||
* size the position is set to the end of the file.
|
||||
*
|
||||
* @param offset is the location to move the file pointer to.
|
||||
*/
|
||||
FileWriter.prototype.seek = function(offset) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See back from end of file.
|
||||
if (offset < 0) {
|
||||
this.position = Math.max(offset + this.length, 0);
|
||||
}
|
||||
// Offset is bigger then file size so set position
|
||||
// to the end of the file.
|
||||
else if (offset > this.length) {
|
||||
this.position = this.length;
|
||||
}
|
||||
// Offset is between 0 and file size so set the position
|
||||
// to start writing.
|
||||
else {
|
||||
this.position = offset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Truncates the file to the size specified.
|
||||
*
|
||||
* @param size to chop the file at.
|
||||
*/
|
||||
FileWriter.prototype.truncate = function(size) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart === "function") {
|
||||
me.onwritestart({"type":"writestart", "target":this});
|
||||
}
|
||||
|
||||
// Write file
|
||||
PhoneGap.exec(
|
||||
// Success callback
|
||||
function(r) {
|
||||
var evt;
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the length of the file
|
||||
me.length = r;
|
||||
me.position = Math.min(me.position, r);
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite === "function") {
|
||||
me.onwrite({"type":"write", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend({"type":"writeend", "target":me});
|
||||
}
|
||||
},
|
||||
// Error callback
|
||||
function(e) {
|
||||
var evt;
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState === FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror === "function") {
|
||||
me.onerror({"type":"error", "target":me});
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend === "function") {
|
||||
me.onwriteend({"type":"writeend", "target":me});
|
||||
}
|
||||
}, "File", "truncate", [this.fileName, size]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the state of the file or directory
|
||||
*
|
||||
* @constructor
|
||||
* {Date} modificationTime (readonly)
|
||||
*/
|
||||
var Metadata = function() {
|
||||
this.modificationTime=null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Supplies arguments to methods that lookup or create files and directories
|
||||
*
|
||||
* @constructor
|
||||
* @param {boolean} create file or directory if it doesn't exist
|
||||
* @param {boolean} exclusive if true the command will fail if the file or directory exists
|
||||
*/
|
||||
var Flags = function(create, exclusive) {
|
||||
this.create = create || false;
|
||||
this.exclusive = exclusive || false;
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface representing a file system
|
||||
*
|
||||
* @constructor
|
||||
* {DOMString} name the unique name of the file system (readonly)
|
||||
* {DirectoryEntry} root directory of the file system (readonly)
|
||||
*/
|
||||
var FileSystem = function() {
|
||||
this.name = null;
|
||||
this.root = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface that lists the files and directories in a directory.
|
||||
* @constructor
|
||||
*/
|
||||
var DirectoryReader = function(fullPath){
|
||||
this.fullPath = fullPath || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a list of entries from a directory.
|
||||
*
|
||||
* @param {Function} successCallback is called with a list of entries
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "readEntries", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface representing a directory on the file system.
|
||||
*
|
||||
* @constructor
|
||||
* {boolean} isFile always false (readonly)
|
||||
* {boolean} isDirectory always true (readonly)
|
||||
* {DOMString} name of the directory, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the directory (readonly)
|
||||
* {FileSystem} filesystem on which the directory resides (readonly)
|
||||
*/
|
||||
var DirectoryEntry = function() {
|
||||
this.isFile = false;
|
||||
this.isDirectory = true;
|
||||
this.name = null;
|
||||
this.fullPath = null;
|
||||
this.filesystem = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies a directory to a new location
|
||||
*
|
||||
* @param {DirectoryEntry} parent the directory to which to copy the entry
|
||||
* @param {DOMString} newName the new name of the entry, defaults to the current name
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "copyTo", [this.fullPath, parent, newName]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Looks up the metadata of the entry
|
||||
*
|
||||
* @param {Function} successCallback is called with a Metadata object
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getMetadata = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getMetadata", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the parent of the entry
|
||||
*
|
||||
* @param {Function} successCallback is called with a parent entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getParent = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getParent", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves a directory to a new location
|
||||
*
|
||||
* @param {DirectoryEntry} parent the directory to which to move the entry
|
||||
* @param {DOMString} newName the new name of the entry, defaults to the current name
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "moveTo", [this.fullPath, parent, newName]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the entry
|
||||
*
|
||||
* @param {Function} successCallback is called with no parameters
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.remove = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "remove", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a URI that can be used to identify this entry.
|
||||
*
|
||||
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
|
||||
* @return uri
|
||||
*/
|
||||
DirectoryEntry.prototype.toURI = function(mimeType) {
|
||||
return "file://" + this.fullPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new DirectoryReader to read entries from this directory
|
||||
*/
|
||||
DirectoryEntry.prototype.createReader = function(successCallback, errorCallback) {
|
||||
return new DirectoryReader(this.fullPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a directory
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
|
||||
* @param {Flags} options to create or excluively create the directory
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getDirectory", [this.fullPath, path, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates or looks up a file
|
||||
*
|
||||
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
|
||||
* @param {Flags} options to create or excluively create the file
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getFile", [this.fullPath, path, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a directory and all of it's contents
|
||||
*
|
||||
* @param {Function} successCallback is called with no parameters
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "removeRecursively", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface representing a directory on the file system.
|
||||
*
|
||||
* @constructor
|
||||
* {boolean} isFile always true (readonly)
|
||||
* {boolean} isDirectory always false (readonly)
|
||||
* {DOMString} name of the file, excluding the path leading to it (readonly)
|
||||
* {DOMString} fullPath the absolute full path to the file (readonly)
|
||||
* {FileSystem} filesystem on which the directory resides (readonly)
|
||||
*/
|
||||
var FileEntry = function() {
|
||||
this.isFile = true;
|
||||
this.isDirectory = false;
|
||||
this.name = null;
|
||||
this.fullPath = null;
|
||||
this.filesystem = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies a file to a new location
|
||||
*
|
||||
* @param {DirectoryEntry} parent the directory to which to copy the entry
|
||||
* @param {DOMString} newName the new name of the entry, defaults to the current name
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "copyTo", [this.fullPath, parent, newName]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Looks up the metadata of the entry
|
||||
*
|
||||
* @param {Function} successCallback is called with a Metadata object
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.getMetadata = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getMetadata", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the parent of the entry
|
||||
*
|
||||
* @param {Function} successCallback is called with a parent entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.getParent = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getParent", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves a directory to a new location
|
||||
*
|
||||
* @param {DirectoryEntry} parent the directory to which to move the entry
|
||||
* @param {DOMString} newName the new name of the entry, defaults to the current name
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "moveTo", [this.fullPath, parent, newName]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the entry
|
||||
*
|
||||
* @param {Function} successCallback is called with no parameters
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.remove = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "remove", [this.fullPath]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a URI that can be used to identify this entry.
|
||||
*
|
||||
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
|
||||
* @return uri
|
||||
*/
|
||||
FileEntry.prototype.toURI = function(mimeType) {
|
||||
return "file://" + this.fullPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new FileWriter associated with the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new FileWriter
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
|
||||
this.file(function(filePointer) {
|
||||
var writer = new FileWriter(filePointer);
|
||||
|
||||
if (writer.fileName === null || writer.fileName === "") {
|
||||
if (typeof errorCallback == "function") {
|
||||
errorCallback({
|
||||
"code": FileError.INVALID_STATE_ERR
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof successCallback == "function") {
|
||||
successCallback(writer);
|
||||
}
|
||||
}, errorCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a File that represents the current state of the file that this FileEntry represents.
|
||||
*
|
||||
* @param {Function} successCallback is called with the new File object
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
FileEntry.prototype.file = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getFileMetadata", [this.fullPath]);
|
||||
};
|
||||
|
||||
/** @constructor */
|
||||
var LocalFileSystem = function() {
|
||||
};
|
||||
|
||||
// File error codes
|
||||
LocalFileSystem.TEMPORARY = 0;
|
||||
LocalFileSystem.PERSISTENT = 1;
|
||||
LocalFileSystem.RESOURCE = 2;
|
||||
LocalFileSystem.APPLICATION = 3;
|
||||
|
||||
/**
|
||||
* Requests a filesystem in which to store application data.
|
||||
*
|
||||
* @param {int} type of file system being requested
|
||||
* @param {Function} successCallback is called with the new FileSystem
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) {
|
||||
if (type < 0 || type > 3) {
|
||||
if (typeof errorCallback == "function") {
|
||||
errorCallback({
|
||||
"code": FileError.SYNTAX_ERR
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "requestFileSystem", [type, size]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {DOMString} uri referring to a local file in a filesystem
|
||||
* @param {Function} successCallback is called with the new entry
|
||||
* @param {Function} errorCallback is called with a FileError
|
||||
*/
|
||||
LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "resolveLocalFileSystemURI", [uri]);
|
||||
};
|
||||
|
||||
/**
|
||||
* This function returns and array of contacts. It is required as we need to convert raw
|
||||
* JSON objects into concrete Contact objects. Currently this method is called after
|
||||
* navigator.service.contacts.find but before the find methods success call back.
|
||||
*
|
||||
* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects.
|
||||
* @returns an entry
|
||||
*/
|
||||
LocalFileSystem.prototype._castFS = function(pluginResult) {
|
||||
var entry = null;
|
||||
entry = new DirectoryEntry();
|
||||
entry.isDirectory = pluginResult.message.root.isDirectory;
|
||||
entry.isFile = pluginResult.message.root.isFile;
|
||||
entry.name = pluginResult.message.root.name;
|
||||
entry.fullPath = pluginResult.message.root.fullPath;
|
||||
pluginResult.message.root = entry;
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
LocalFileSystem.prototype._castEntry = function(pluginResult) {
|
||||
var entry = null;
|
||||
if (pluginResult.message.isDirectory) {
|
||||
console.log("This is a dir");
|
||||
entry = new DirectoryEntry();
|
||||
}
|
||||
else if (pluginResult.message.isFile) {
|
||||
console.log("This is a file");
|
||||
entry = new FileEntry();
|
||||
}
|
||||
entry.isDirectory = pluginResult.message.isDirectory;
|
||||
entry.isFile = pluginResult.message.isFile;
|
||||
entry.name = pluginResult.message.name;
|
||||
entry.fullPath = pluginResult.message.fullPath;
|
||||
pluginResult.message = entry;
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
LocalFileSystem.prototype._castEntries = function(pluginResult) {
|
||||
var entries = pluginResult.message;
|
||||
var retVal = [];
|
||||
for (var i=0; i<entries.length; i++) {
|
||||
retVal.push(window.localFileSystem._createEntry(entries[i]));
|
||||
}
|
||||
pluginResult.message = retVal;
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
LocalFileSystem.prototype._createEntry = function(castMe) {
|
||||
var entry = null;
|
||||
if (castMe.isDirectory) {
|
||||
console.log("This is a dir");
|
||||
entry = new DirectoryEntry();
|
||||
}
|
||||
else if (castMe.isFile) {
|
||||
console.log("This is a file");
|
||||
entry = new FileEntry();
|
||||
}
|
||||
entry.isDirectory = castMe.isDirectory;
|
||||
entry.isFile = castMe.isFile;
|
||||
entry.name = castMe.name;
|
||||
entry.fullPath = castMe.fullPath;
|
||||
return entry;
|
||||
};
|
||||
|
||||
LocalFileSystem.prototype._castDate = function(pluginResult) {
|
||||
if (pluginResult.message.modificationTime) {
|
||||
var modTime = new Date(pluginResult.message.modificationTime);
|
||||
pluginResult.message.modificationTime = modTime;
|
||||
}
|
||||
else if (pluginResult.message.lastModifiedDate) {
|
||||
var file = new File();
|
||||
file.size = pluginResult.message.size;
|
||||
file.type = pluginResult.message.type;
|
||||
file.name = pluginResult.message.name;
|
||||
file.fullPath = pluginResult.message.fullPath;
|
||||
file.lastModifiedDate = new Date(pluginResult.message.lastModifiedDate);
|
||||
pluginResult.message = file;
|
||||
}
|
||||
return pluginResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the FileSystem interface into the browser.
|
||||
*/
|
||||
PhoneGap.addConstructor(function() {
|
||||
var pgLocalFileSystem = new LocalFileSystem();
|
||||
// Needed for cast methods
|
||||
if(typeof window.localFileSystem == "undefined") window.localFileSystem = pgLocalFileSystem;
|
||||
if(typeof window.requestFileSystem == "undefined") window.requestFileSystem = pgLocalFileSystem.requestFileSystem;
|
||||
if(typeof window.resolveLocalFileSystemURI == "undefined") window.resolveLocalFileSystemURI = pgLocalFileSystem.resolveLocalFileSystemURI;
|
||||
});
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("filetransfer")) {
|
||||
PhoneGap.addResource("filetransfer");
|
||||
|
||||
/**
|
||||
* FileTransfer uploads a file to a remote server.
|
||||
* @constructor
|
||||
*/
|
||||
var FileTransfer = function() {};
|
||||
|
||||
/**
|
||||
* FileUploadResult
|
||||
* @constructor
|
||||
*/
|
||||
var FileUploadResult = function() {
|
||||
this.bytesSent = 0;
|
||||
this.responseCode = null;
|
||||
this.response = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* FileTransferError
|
||||
* @constructor
|
||||
*/
|
||||
var FileTransferError = function() {
|
||||
this.code = null;
|
||||
};
|
||||
|
||||
FileTransferError.FILE_NOT_FOUND_ERR = 1;
|
||||
FileTransferError.INVALID_URL_ERR = 2;
|
||||
FileTransferError.CONNECTION_ERR = 3;
|
||||
|
||||
/**
|
||||
* Given an absolute file path, uploads a file on the device to a remote server
|
||||
* using a multipart HTTP request.
|
||||
* @param filePath {String} Full path of the file on the device
|
||||
* @param server {String} URL of the server to receive the file
|
||||
* @param successCallback (Function} Callback to be invoked when upload has completed
|
||||
* @param errorCallback {Function} Callback to be invoked upon error
|
||||
* @param options {FileUploadOptions} Optional parameters such as file name and mimetype
|
||||
*/
|
||||
FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, debug) {
|
||||
|
||||
// check for options
|
||||
var fileKey = null;
|
||||
var fileName = null;
|
||||
var mimeType = null;
|
||||
var params = null;
|
||||
var chunkedMode = true;
|
||||
if (options) {
|
||||
fileKey = options.fileKey;
|
||||
fileName = options.fileName;
|
||||
mimeType = options.mimeType;
|
||||
if (options.chunkedMode != null || typeof options.chunkedMode != "undefined") {
|
||||
chunkedMode = options.chunkedMode;
|
||||
}
|
||||
if (options.params) {
|
||||
params = options.params;
|
||||
}
|
||||
else {
|
||||
params = {};
|
||||
}
|
||||
}
|
||||
|
||||
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, debug, chunkedMode]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Options to customize the HTTP request used to upload files.
|
||||
* @constructor
|
||||
* @param fileKey {String} Name of file request parameter.
|
||||
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
|
||||
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
|
||||
* @param params {Object} Object with key: value params to send to the server.
|
||||
*/
|
||||
var FileUploadOptions = function(fileKey, fileName, mimeType, params) {
|
||||
this.fileKey = fileKey || null;
|
||||
this.fileName = fileName || null;
|
||||
this.mimeType = mimeType || null;
|
||||
this.params = params || null;
|
||||
};
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("geolocation")) {
|
||||
PhoneGap.addResource("geolocation");
|
||||
|
||||
/**
|
||||
* This class provides access to device GPS data.
|
||||
* @constructor
|
||||
*/
|
||||
var Geolocation = function() {
|
||||
|
||||
// The last known GPS position.
|
||||
this.lastPosition = null;
|
||||
|
||||
// Geolocation listeners
|
||||
this.listeners = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Position error object
|
||||
*
|
||||
* @constructor
|
||||
* @param code
|
||||
* @param message
|
||||
*/
|
||||
var PositionError = function(code, message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
};
|
||||
|
||||
PositionError.PERMISSION_DENIED = 1;
|
||||
PositionError.POSITION_UNAVAILABLE = 2;
|
||||
PositionError.TIMEOUT = 3;
|
||||
|
||||
/**
|
||||
* Asynchronously aquires the current position.
|
||||
*
|
||||
* @param {Function} successCallback The function to call when the position data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the heading position. (OPTIONAL)
|
||||
* @param {PositionOptions} options The options for getting the position data. (OPTIONAL)
|
||||
*/
|
||||
Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) {
|
||||
if (navigator._geo.listeners.global) {
|
||||
console.log("Geolocation Error: Still waiting for previous getCurrentPosition() request.");
|
||||
try {
|
||||
errorCallback(new PositionError(PositionError.TIMEOUT, "Geolocation Error: Still waiting for previous getCurrentPosition() request."));
|
||||
} catch (e) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
var maximumAge = 10000;
|
||||
var enableHighAccuracy = false;
|
||||
var timeout = 10000;
|
||||
if (typeof options !== "undefined") {
|
||||
if (typeof options.maximumAge !== "undefined") {
|
||||
maximumAge = options.maximumAge;
|
||||
}
|
||||
if (typeof options.enableHighAccuracy !== "undefined") {
|
||||
enableHighAccuracy = options.enableHighAccuracy;
|
||||
}
|
||||
if (typeof options.timeout !== "undefined") {
|
||||
timeout = options.timeout;
|
||||
}
|
||||
}
|
||||
navigator._geo.listeners.global = {"success" : successCallback, "fail" : errorCallback };
|
||||
PhoneGap.exec(null, null, "Geolocation", "getCurrentLocation", [enableHighAccuracy, timeout, maximumAge]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronously watches the geolocation for changes to geolocation. When a change occurs,
|
||||
* the successCallback is called with the new location.
|
||||
*
|
||||
* @param {Function} successCallback The function to call each time the location data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the location data. (OPTIONAL)
|
||||
* @param {PositionOptions} options The options for getting the location data such as frequency. (OPTIONAL)
|
||||
* @return String The watch id that must be passed to #clearWatch to stop watching.
|
||||
*/
|
||||
Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) {
|
||||
var maximumAge = 10000;
|
||||
var enableHighAccuracy = false;
|
||||
var timeout = 10000;
|
||||
if (typeof options !== "undefined") {
|
||||
if (typeof options.frequency !== "undefined") {
|
||||
maximumAge = options.frequency;
|
||||
}
|
||||
if (typeof options.maximumAge !== "undefined") {
|
||||
maximumAge = options.maximumAge;
|
||||
}
|
||||
if (typeof options.enableHighAccuracy !== "undefined") {
|
||||
enableHighAccuracy = options.enableHighAccuracy;
|
||||
}
|
||||
if (typeof options.timeout !== "undefined") {
|
||||
timeout = options.timeout;
|
||||
}
|
||||
}
|
||||
var id = PhoneGap.createUUID();
|
||||
navigator._geo.listeners[id] = {"success" : successCallback, "fail" : errorCallback };
|
||||
PhoneGap.exec(null, null, "Geolocation", "start", [id, enableHighAccuracy, timeout, maximumAge]);
|
||||
return id;
|
||||
};
|
||||
|
||||
/*
|
||||
* Native callback when watch position has a new position.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param {String} id
|
||||
* @param {Number} lat
|
||||
* @param {Number} lng
|
||||
* @param {Number} alt
|
||||
* @param {Number} altacc
|
||||
* @param {Number} head
|
||||
* @param {Number} vel
|
||||
* @param {Number} stamp
|
||||
*/
|
||||
Geolocation.prototype.success = function(id, lat, lng, alt, altacc, head, vel, stamp) {
|
||||
var coords = new Coordinates(lat, lng, alt, altacc, head, vel);
|
||||
var loc = new Position(coords, stamp);
|
||||
try {
|
||||
if (lat === "undefined" || lng === "undefined") {
|
||||
navigator._geo.listeners[id].fail(new PositionError(PositionError.POSITION_UNAVAILABLE, "Lat/Lng are undefined."));
|
||||
}
|
||||
else {
|
||||
navigator._geo.lastPosition = loc;
|
||||
navigator._geo.listeners[id].success(loc);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.log("Geolocation Error: Error calling success callback function.");
|
||||
}
|
||||
|
||||
if (id === "global") {
|
||||
delete navigator._geo.listeners.global;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Native callback when watch position has an error.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param {String} id The ID of the watch
|
||||
* @param {Number} code The error code
|
||||
* @param {String} msg The error message
|
||||
*/
|
||||
Geolocation.prototype.fail = function(id, code, msg) {
|
||||
try {
|
||||
navigator._geo.listeners[id].fail(new PositionError(code, msg));
|
||||
}
|
||||
catch (e) {
|
||||
console.log("Geolocation Error: Error calling error callback function.");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the specified heading watch.
|
||||
*
|
||||
* @param {String} id The ID of the watch returned from #watchPosition
|
||||
*/
|
||||
Geolocation.prototype.clearWatch = function(id) {
|
||||
PhoneGap.exec(null, null, "Geolocation", "stop", [id]);
|
||||
delete navigator._geo.listeners[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Force the PhoneGap geolocation to be used instead of built-in.
|
||||
*/
|
||||
Geolocation.usingPhoneGap = false;
|
||||
Geolocation.usePhoneGap = function() {
|
||||
if (Geolocation.usingPhoneGap) {
|
||||
return;
|
||||
}
|
||||
Geolocation.usingPhoneGap = true;
|
||||
|
||||
// Set built-in geolocation methods to our own implementations
|
||||
// (Cannot replace entire geolocation, but can replace individual methods)
|
||||
navigator.geolocation.setLocation = navigator._geo.setLocation;
|
||||
navigator.geolocation.getCurrentPosition = navigator._geo.getCurrentPosition;
|
||||
navigator.geolocation.watchPosition = navigator._geo.watchPosition;
|
||||
navigator.geolocation.clearWatch = navigator._geo.clearWatch;
|
||||
navigator.geolocation.start = navigator._geo.start;
|
||||
navigator.geolocation.stop = navigator._geo.stop;
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
navigator._geo = new Geolocation();
|
||||
|
||||
// No native geolocation object for Android 1.x, so use PhoneGap geolocation
|
||||
if (typeof navigator.geolocation === 'undefined') {
|
||||
navigator.geolocation = navigator._geo;
|
||||
Geolocation.usingPhoneGap = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("media")) {
|
||||
PhoneGap.addResource("media");
|
||||
|
||||
/**
|
||||
* This class provides access to the device media, interfaces to both sound and video
|
||||
*
|
||||
* @constructor
|
||||
* @param src The file name or url to play
|
||||
* @param successCallback The callback to be called when the file is done playing or recording.
|
||||
* successCallback() - OPTIONAL
|
||||
* @param errorCallback The callback to be called if there is an error.
|
||||
* errorCallback(int errorCode) - OPTIONAL
|
||||
* @param statusCallback The callback to be called when media status has changed.
|
||||
* statusCallback(int statusCode) - OPTIONAL
|
||||
* @param positionCallback The callback to be called when media position has changed.
|
||||
* positionCallback(long position) - OPTIONAL
|
||||
*/
|
||||
var Media = function(src, successCallback, errorCallback, statusCallback, positionCallback) {
|
||||
|
||||
// successCallback optional
|
||||
if (successCallback && (typeof successCallback !== "function")) {
|
||||
console.log("Media Error: successCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// errorCallback optional
|
||||
if (errorCallback && (typeof errorCallback !== "function")) {
|
||||
console.log("Media Error: errorCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// statusCallback optional
|
||||
if (statusCallback && (typeof statusCallback !== "function")) {
|
||||
console.log("Media Error: statusCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
// statusCallback optional
|
||||
if (positionCallback && (typeof positionCallback !== "function")) {
|
||||
console.log("Media Error: positionCallback is not a function");
|
||||
return;
|
||||
}
|
||||
|
||||
this.id = PhoneGap.createUUID();
|
||||
PhoneGap.mediaObjects[this.id] = this;
|
||||
this.src = src;
|
||||
this.successCallback = successCallback;
|
||||
this.errorCallback = errorCallback;
|
||||
this.statusCallback = statusCallback;
|
||||
this.positionCallback = positionCallback;
|
||||
this._duration = -1;
|
||||
this._position = -1;
|
||||
};
|
||||
|
||||
// Media messages
|
||||
Media.MEDIA_STATE = 1;
|
||||
Media.MEDIA_DURATION = 2;
|
||||
Media.MEDIA_POSITION = 3;
|
||||
Media.MEDIA_ERROR = 9;
|
||||
|
||||
// Media states
|
||||
Media.MEDIA_NONE = 0;
|
||||
Media.MEDIA_STARTING = 1;
|
||||
Media.MEDIA_RUNNING = 2;
|
||||
Media.MEDIA_PAUSED = 3;
|
||||
Media.MEDIA_STOPPED = 4;
|
||||
Media.MEDIA_MSG = ["None", "Starting", "Running", "Paused", "Stopped"];
|
||||
|
||||
// TODO: Will MediaError be used?
|
||||
/**
|
||||
* This class contains information about any Media errors.
|
||||
* @constructor
|
||||
*/
|
||||
var MediaError = function() {
|
||||
this.code = null;
|
||||
this.message = "";
|
||||
};
|
||||
|
||||
MediaError.MEDIA_ERR_NONE_ACTIVE = 0;
|
||||
MediaError.MEDIA_ERR_ABORTED = 1;
|
||||
MediaError.MEDIA_ERR_NETWORK = 2;
|
||||
MediaError.MEDIA_ERR_DECODE = 3;
|
||||
MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;
|
||||
|
||||
/**
|
||||
* Start or resume playing audio file.
|
||||
*/
|
||||
Media.prototype.play = function() {
|
||||
PhoneGap.exec(null, null, "Media", "startPlayingAudio", [this.id, this.src]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop playing audio file.
|
||||
*/
|
||||
Media.prototype.stop = function() {
|
||||
return PhoneGap.exec(null, null, "Media", "stopPlayingAudio", [this.id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Seek or jump to a new time in the track..
|
||||
*/
|
||||
Media.prototype.seekTo = function(milliseconds) {
|
||||
PhoneGap.exec(null, null, "Media", "seekToAudio", [this.id, milliseconds]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Pause playing audio file.
|
||||
*/
|
||||
Media.prototype.pause = function() {
|
||||
PhoneGap.exec(null, null, "Media", "pausePlayingAudio", [this.id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get duration of an audio file.
|
||||
* The duration is only set for audio that is playing, paused or stopped.
|
||||
*
|
||||
* @return duration or -1 if not known.
|
||||
*/
|
||||
Media.prototype.getDuration = function() {
|
||||
return this._duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get position of audio.
|
||||
*/
|
||||
Media.prototype.getCurrentPosition = function(success, fail) {
|
||||
PhoneGap.exec(success, fail, "Media", "getCurrentPositionAudio", [this.id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Start recording audio file.
|
||||
*/
|
||||
Media.prototype.startRecord = function() {
|
||||
PhoneGap.exec(null, null, "Media", "startRecordingAudio", [this.id, this.src]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop recording audio file.
|
||||
*/
|
||||
Media.prototype.stopRecord = function() {
|
||||
PhoneGap.exec(null, null, "Media", "stopRecordingAudio", [this.id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Release the resources.
|
||||
*/
|
||||
Media.prototype.release = function() {
|
||||
PhoneGap.exec(null, null, "Media", "release", [this.id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjust the volume.
|
||||
*/
|
||||
Media.prototype.setVolume = function(volume) {
|
||||
PhoneGap.exec(null, null, "Media", "setVolume", [this.id, volume]);
|
||||
};
|
||||
|
||||
/**
|
||||
* List of media objects.
|
||||
* PRIVATE
|
||||
*/
|
||||
PhoneGap.mediaObjects = {};
|
||||
|
||||
/**
|
||||
* Object that receives native callbacks.
|
||||
* PRIVATE
|
||||
* @constructor
|
||||
*/
|
||||
PhoneGap.Media = function() {};
|
||||
|
||||
/**
|
||||
* Get the media object.
|
||||
* PRIVATE
|
||||
*
|
||||
* @param id The media object id (string)
|
||||
*/
|
||||
PhoneGap.Media.getMediaObject = function(id) {
|
||||
return PhoneGap.mediaObjects[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Audio has status update.
|
||||
* PRIVATE
|
||||
*
|
||||
* @param id The media object id (string)
|
||||
* @param status The status code (int)
|
||||
* @param msg The status message (string)
|
||||
*/
|
||||
PhoneGap.Media.onStatus = function(id, msg, value) {
|
||||
var media = PhoneGap.mediaObjects[id];
|
||||
// If state update
|
||||
if (msg === Media.MEDIA_STATE) {
|
||||
if (value === Media.MEDIA_STOPPED) {
|
||||
if (media.successCallback) {
|
||||
media.successCallback();
|
||||
}
|
||||
}
|
||||
if (media.statusCallback) {
|
||||
media.statusCallback(value);
|
||||
}
|
||||
}
|
||||
else if (msg === Media.MEDIA_DURATION) {
|
||||
media._duration = value;
|
||||
}
|
||||
else if (msg === Media.MEDIA_ERROR) {
|
||||
if (media.errorCallback) {
|
||||
media.errorCallback({"code":value});
|
||||
}
|
||||
}
|
||||
else if (msg == Media.MEDIA_POSITION) {
|
||||
media._position = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("network")) {
|
||||
PhoneGap.addResource("network");
|
||||
|
||||
/**
|
||||
* This class contains information about the current network Connection.
|
||||
* @constructor
|
||||
*/
|
||||
var Connection = function() {
|
||||
this.type = null;
|
||||
this._firstRun = true;
|
||||
this._timer = null;
|
||||
this.timeout = 500;
|
||||
|
||||
var me = this;
|
||||
this.getInfo(
|
||||
function(type) {
|
||||
// Need to send events if we are on or offline
|
||||
if (type == "none") {
|
||||
// set a timer if still offline at the end of timer send the offline event
|
||||
me._timer = setTimeout(function(){
|
||||
me.type = type;
|
||||
PhoneGap.fireDocumentEvent('offline');
|
||||
me._timer = null;
|
||||
}, me.timeout);
|
||||
} else {
|
||||
// If there is a current offline event pending clear it
|
||||
if (me._timer != null) {
|
||||
clearTimeout(me._timer);
|
||||
me._timer = null;
|
||||
}
|
||||
me.type = type;
|
||||
PhoneGap.fireDocumentEvent('online');
|
||||
}
|
||||
|
||||
// should only fire this once
|
||||
if (me._firstRun) {
|
||||
me._firstRun = false;
|
||||
PhoneGap.onPhoneGapConnectionReady.fire();
|
||||
}
|
||||
},
|
||||
function(e) {
|
||||
// If we can't get the network info we should still tell PhoneGap
|
||||
// to fire the deviceready event.
|
||||
if (me._firstRun) {
|
||||
me._firstRun = false;
|
||||
PhoneGap.onPhoneGapConnectionReady.fire();
|
||||
}
|
||||
console.log("Error initializing Network Connection: " + e);
|
||||
});
|
||||
};
|
||||
|
||||
Connection.UNKNOWN = "unknown";
|
||||
Connection.ETHERNET = "ethernet";
|
||||
Connection.WIFI = "wifi";
|
||||
Connection.CELL_2G = "2g";
|
||||
Connection.CELL_3G = "3g";
|
||||
Connection.CELL_4G = "4g";
|
||||
Connection.NONE = "none";
|
||||
|
||||
/**
|
||||
* Get connection info
|
||||
*
|
||||
* @param {Function} successCallback The function to call when the Connection data is available
|
||||
* @param {Function} errorCallback The function to call when there is an error getting the Connection data. (OPTIONAL)
|
||||
*/
|
||||
Connection.prototype.getInfo = function(successCallback, errorCallback) {
|
||||
// Get info
|
||||
PhoneGap.exec(successCallback, errorCallback, "Network Status", "getConnectionInfo", []);
|
||||
};
|
||||
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.network === "undefined") {
|
||||
navigator.network = new Object();
|
||||
}
|
||||
if (typeof navigator.network.connection === "undefined") {
|
||||
navigator.network.connection = new Connection();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("notification")) {
|
||||
PhoneGap.addResource("notification");
|
||||
|
||||
/**
|
||||
* This class provides access to notifications on the device.
|
||||
* @constructor
|
||||
*/
|
||||
var Notification = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a native alert dialog, with a customizable title and button text.
|
||||
*
|
||||
* @param {String} message Message to print in the body of the alert
|
||||
* @param {Function} completeCallback The callback that is called when user clicks on a button.
|
||||
* @param {String} title Title of the alert dialog (default: Alert)
|
||||
* @param {String} buttonLabel Label of the close button (default: OK)
|
||||
*/
|
||||
Notification.prototype.alert = function(message, completeCallback, title, buttonLabel) {
|
||||
var _title = (title || "Alert");
|
||||
var _buttonLabel = (buttonLabel || "OK");
|
||||
PhoneGap.exec(completeCallback, null, "Notification", "alert", [message,_title,_buttonLabel]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a native confirm dialog, with a customizable title and button text.
|
||||
* The result that the user selects is returned to the result callback.
|
||||
*
|
||||
* @param {String} message Message to print in the body of the alert
|
||||
* @param {Function} resultCallback The callback that is called when user clicks on a button.
|
||||
* @param {String} title Title of the alert dialog (default: Confirm)
|
||||
* @param {String} buttonLabels Comma separated list of the labels of the buttons (default: 'OK,Cancel')
|
||||
*/
|
||||
Notification.prototype.confirm = function(message, resultCallback, title, buttonLabels) {
|
||||
var _title = (title || "Confirm");
|
||||
var _buttonLabels = (buttonLabels || "OK,Cancel");
|
||||
PhoneGap.exec(resultCallback, null, "Notification", "confirm", [message,_title,_buttonLabels]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Start spinning the activity indicator on the statusbar
|
||||
*/
|
||||
Notification.prototype.activityStart = function() {
|
||||
PhoneGap.exec(null, null, "Notification", "activityStart", ["Busy","Please wait..."]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop spinning the activity indicator on the statusbar, if it's currently spinning
|
||||
*/
|
||||
Notification.prototype.activityStop = function() {
|
||||
PhoneGap.exec(null, null, "Notification", "activityStop", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Display a progress dialog with progress bar that goes from 0 to 100.
|
||||
*
|
||||
* @param {String} title Title of the progress dialog.
|
||||
* @param {String} message Message to display in the dialog.
|
||||
*/
|
||||
Notification.prototype.progressStart = function(title, message) {
|
||||
PhoneGap.exec(null, null, "Notification", "progressStart", [title, message]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the progress dialog value.
|
||||
*
|
||||
* @param {Number} value 0-100
|
||||
*/
|
||||
Notification.prototype.progressValue = function(value) {
|
||||
PhoneGap.exec(null, null, "Notification", "progressValue", [value]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the progress dialog.
|
||||
*/
|
||||
Notification.prototype.progressStop = function() {
|
||||
PhoneGap.exec(null, null, "Notification", "progressStop", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Causes the device to blink a status LED.
|
||||
*
|
||||
* @param {Integer} count The number of blinks.
|
||||
* @param {String} colour The colour of the light.
|
||||
*/
|
||||
Notification.prototype.blink = function(count, colour) {
|
||||
// NOT IMPLEMENTED
|
||||
};
|
||||
|
||||
/**
|
||||
* Causes the device to vibrate.
|
||||
*
|
||||
* @param {Integer} mills The number of milliseconds to vibrate for.
|
||||
*/
|
||||
Notification.prototype.vibrate = function(mills) {
|
||||
PhoneGap.exec(null, null, "Notification", "vibrate", [mills]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Causes the device to beep.
|
||||
* On Android, the default notification ringtone is played "count" times.
|
||||
*
|
||||
* @param {Integer} count The number of beeps.
|
||||
*/
|
||||
Notification.prototype.beep = function(count) {
|
||||
PhoneGap.exec(null, null, "Notification", "beep", [count]);
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.notification === "undefined") {
|
||||
navigator.notification = new Notification();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("position")) {
|
||||
PhoneGap.addResource("position");
|
||||
|
||||
/**
|
||||
* This class contains position information.
|
||||
* @param {Object} lat
|
||||
* @param {Object} lng
|
||||
* @param {Object} acc
|
||||
* @param {Object} alt
|
||||
* @param {Object} altacc
|
||||
* @param {Object} head
|
||||
* @param {Object} vel
|
||||
* @constructor
|
||||
*/
|
||||
var Position = function(coords, timestamp) {
|
||||
this.coords = coords;
|
||||
this.timestamp = (timestamp !== 'undefined') ? timestamp : new Date().getTime();
|
||||
};
|
||||
|
||||
/** @constructor */
|
||||
var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) {
|
||||
/**
|
||||
* The latitude of the position.
|
||||
*/
|
||||
this.latitude = lat;
|
||||
/**
|
||||
* The longitude of the position,
|
||||
*/
|
||||
this.longitude = lng;
|
||||
/**
|
||||
* The accuracy of the position.
|
||||
*/
|
||||
this.accuracy = acc;
|
||||
/**
|
||||
* The altitude of the position.
|
||||
*/
|
||||
this.altitude = alt;
|
||||
/**
|
||||
* The direction the device is moving at the position.
|
||||
*/
|
||||
this.heading = head;
|
||||
/**
|
||||
* The velocity with which the device is moving at the position.
|
||||
*/
|
||||
this.speed = vel;
|
||||
/**
|
||||
* The altitude accuracy of the position.
|
||||
*/
|
||||
this.altitudeAccuracy = (altacc !== 'undefined') ? altacc : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class specifies the options for requesting position data.
|
||||
* @constructor
|
||||
*/
|
||||
var PositionOptions = function() {
|
||||
/**
|
||||
* Specifies the desired position accuracy.
|
||||
*/
|
||||
this.enableHighAccuracy = true;
|
||||
/**
|
||||
* The timeout after which if position data cannot be obtained the errorCallback
|
||||
* is called.
|
||||
*/
|
||||
this.timeout = 10000;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class contains information about any GSP errors.
|
||||
* @constructor
|
||||
*/
|
||||
var PositionError = function() {
|
||||
this.code = null;
|
||||
this.message = "";
|
||||
};
|
||||
|
||||
PositionError.UNKNOWN_ERROR = 0;
|
||||
PositionError.PERMISSION_DENIED = 1;
|
||||
PositionError.POSITION_UNAVAILABLE = 2;
|
||||
PositionError.TIMEOUT = 3;
|
||||
}
|
||||
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is purely for the Android 1.5/1.6 HTML 5 Storage
|
||||
* I was hoping that Android 2.0 would deprecate this, but given the fact that
|
||||
* most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required
|
||||
*/
|
||||
|
||||
if (!PhoneGap.hasResource("storage")) {
|
||||
PhoneGap.addResource("storage");
|
||||
|
||||
/**
|
||||
* SQL result set object
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DroidDB_Rows = function() {
|
||||
this.resultSet = []; // results array
|
||||
this.length = 0; // number of rows
|
||||
};
|
||||
|
||||
/**
|
||||
* Get item from SQL result set
|
||||
*
|
||||
* @param row The row number to return
|
||||
* @return The row object
|
||||
*/
|
||||
DroidDB_Rows.prototype.item = function(row) {
|
||||
return this.resultSet[row];
|
||||
};
|
||||
|
||||
/**
|
||||
* SQL result set that is returned to user.
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DroidDB_Result = function() {
|
||||
this.rows = new DroidDB_Rows();
|
||||
};
|
||||
|
||||
/**
|
||||
* Storage object that is called by native code when performing queries.
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DroidDB = function() {
|
||||
this.queryQueue = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query is complete.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DroidDB.prototype.completeQuery = function(id, data) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
delete this.queryQueue[id];
|
||||
|
||||
// Get transaction
|
||||
var tx = query.tx;
|
||||
|
||||
// If transaction hasn't failed
|
||||
// Note: We ignore all query results if previous query
|
||||
// in the same transaction failed.
|
||||
if (tx && tx.queryList[id]) {
|
||||
|
||||
// Save query results
|
||||
var r = new DroidDB_Result();
|
||||
r.rows.resultSet = data;
|
||||
r.rows.length = data.length;
|
||||
try {
|
||||
if (typeof query.successCallback === 'function') {
|
||||
query.successCallback(query.tx, r);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log("executeSql error calling user success callback: "+ex);
|
||||
}
|
||||
|
||||
tx.queryComplete(id);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("executeSql error: "+e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query fails
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param reason Error message
|
||||
* @param id Query id
|
||||
*/
|
||||
DroidDB.prototype.fail = function(reason, id) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
delete this.queryQueue[id];
|
||||
|
||||
// Get transaction
|
||||
var tx = query.tx;
|
||||
|
||||
// If transaction hasn't failed
|
||||
// Note: We ignore all query results if previous query
|
||||
// in the same transaction failed.
|
||||
if (tx && tx.queryList[id]) {
|
||||
tx.queryList = {};
|
||||
|
||||
try {
|
||||
if (typeof query.errorCallback === 'function') {
|
||||
query.errorCallback(query.tx, reason);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log("executeSql error calling user error callback: "+ex);
|
||||
}
|
||||
|
||||
tx.queryFailed(id, reason);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.log("executeSql error: "+e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* SQL query object
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @constructor
|
||||
* @param tx The transaction object that this query belongs to
|
||||
*/
|
||||
var DroidDB_Query = function(tx) {
|
||||
|
||||
// Set the id of the query
|
||||
this.id = PhoneGap.createUUID();
|
||||
|
||||
// Add this query to the queue
|
||||
droiddb.queryQueue[this.id] = this;
|
||||
|
||||
// Init result
|
||||
this.resultSet = [];
|
||||
|
||||
// Set transaction that this query belongs to
|
||||
this.tx = tx;
|
||||
|
||||
// Add this query to transaction list
|
||||
this.tx.queryList[this.id] = this;
|
||||
|
||||
// Callbacks
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Transaction object
|
||||
* PRIVATE METHOD
|
||||
* @constructor
|
||||
*/
|
||||
var DroidDB_Tx = function() {
|
||||
|
||||
// Set the id of the transaction
|
||||
this.id = PhoneGap.createUUID();
|
||||
|
||||
// Callbacks
|
||||
this.successCallback = null;
|
||||
this.errorCallback = null;
|
||||
|
||||
// Query list
|
||||
this.queryList = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark query in transaction as complete.
|
||||
* If all queries are complete, call the user's transaction success callback.
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DroidDB_Tx.prototype.queryComplete = function(id) {
|
||||
delete this.queryList[id];
|
||||
|
||||
// If no more outstanding queries, then fire transaction success
|
||||
if (this.successCallback) {
|
||||
var count = 0;
|
||||
var i;
|
||||
for (i in this.queryList) {
|
||||
if (this.queryList.hasOwnProperty(i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count === 0) {
|
||||
try {
|
||||
this.successCallback();
|
||||
} catch(e) {
|
||||
console.log("Transaction error calling user success callback: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark query in transaction as failed.
|
||||
*
|
||||
* @param id Query id
|
||||
* @param reason Error message
|
||||
*/
|
||||
DroidDB_Tx.prototype.queryFailed = function(id, reason) {
|
||||
|
||||
// The sql queries in this transaction have already been run, since
|
||||
// we really don't have a real transaction implemented in native code.
|
||||
// However, the user callbacks for the remaining sql queries in transaction
|
||||
// will not be called.
|
||||
this.queryList = {};
|
||||
|
||||
if (this.errorCallback) {
|
||||
try {
|
||||
this.errorCallback(reason);
|
||||
} catch(e) {
|
||||
console.log("Transaction error calling user error callback: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute SQL statement
|
||||
*
|
||||
* @param sql SQL statement to execute
|
||||
* @param params Statement parameters
|
||||
* @param successCallback Success callback
|
||||
* @param errorCallback Error callback
|
||||
*/
|
||||
DroidDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCallback) {
|
||||
|
||||
// Init params array
|
||||
if (typeof params === 'undefined') {
|
||||
params = [];
|
||||
}
|
||||
|
||||
// Create query and add to queue
|
||||
var query = new DroidDB_Query(this);
|
||||
droiddb.queryQueue[query.id] = query;
|
||||
|
||||
// Save callbacks
|
||||
query.successCallback = successCallback;
|
||||
query.errorCallback = errorCallback;
|
||||
|
||||
// Call native code
|
||||
PhoneGap.exec(null, null, "Storage", "executeSql", [sql, params, query.id]);
|
||||
};
|
||||
|
||||
var DatabaseShell = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Start a transaction.
|
||||
* Does not support rollback in event of failure.
|
||||
*
|
||||
* @param process {Function} The transaction function
|
||||
* @param successCallback {Function}
|
||||
* @param errorCallback {Function}
|
||||
*/
|
||||
DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
|
||||
var tx = new DroidDB_Tx();
|
||||
tx.successCallback = successCallback;
|
||||
tx.errorCallback = errorCallback;
|
||||
try {
|
||||
process(tx);
|
||||
} catch (e) {
|
||||
console.log("Transaction error: "+e);
|
||||
if (tx.errorCallback) {
|
||||
try {
|
||||
tx.errorCallback(e);
|
||||
} catch (ex) {
|
||||
console.log("Transaction error calling user error callback: "+e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open database
|
||||
*
|
||||
* @param name Database name
|
||||
* @param version Database version
|
||||
* @param display_name Database display name
|
||||
* @param size Database size in bytes
|
||||
* @return Database object
|
||||
*/
|
||||
var DroidDB_openDatabase = function(name, version, display_name, size) {
|
||||
PhoneGap.exec(null, null, "Storage", "openDatabase", [name, version, display_name, size]);
|
||||
var db = new DatabaseShell();
|
||||
return db;
|
||||
};
|
||||
|
||||
/**
|
||||
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
|
||||
* TODO: Do similar for sessionStorage.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
var CupcakeLocalStorage = function() {
|
||||
try {
|
||||
|
||||
this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440);
|
||||
var storage = {};
|
||||
this.length = 0;
|
||||
function setLength (length) {
|
||||
this.length = length;
|
||||
localStorage.length = length;
|
||||
}
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
var i;
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
transaction.executeSql('SELECT * FROM storage', [], function(tx, result) {
|
||||
for(var i = 0; i < result.rows.length; i++) {
|
||||
storage[result.rows.item(i)['id']] = result.rows.item(i)['body'];
|
||||
}
|
||||
setLength(result.rows.length);
|
||||
PhoneGap.initializationComplete("cupcakeStorage");
|
||||
});
|
||||
|
||||
},
|
||||
function (err) {
|
||||
alert(err.message);
|
||||
}
|
||||
);
|
||||
this.setItem = function(key, val) {
|
||||
if (typeof(storage[key])=='undefined') {
|
||||
this.length++;
|
||||
}
|
||||
storage[key] = val;
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
transaction.executeSql('REPLACE INTO storage (id, body) values(?,?)', [key,val]);
|
||||
}
|
||||
);
|
||||
};
|
||||
this.getItem = function(key) {
|
||||
return storage[key];
|
||||
};
|
||||
this.removeItem = function(key) {
|
||||
delete storage[key];
|
||||
this.length--;
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
transaction.executeSql('DELETE FROM storage where id=?', [key]);
|
||||
}
|
||||
);
|
||||
};
|
||||
this.clear = function() {
|
||||
storage = {};
|
||||
this.length = 0;
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
transaction.executeSql('DELETE FROM storage', []);
|
||||
}
|
||||
);
|
||||
};
|
||||
this.key = function(index) {
|
||||
var i = 0;
|
||||
for (var j in storage) {
|
||||
if (i==index) {
|
||||
return j;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
} catch(e) {
|
||||
alert("Database error "+e+".");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
var setupDroidDB = function() {
|
||||
navigator.openDatabase = window.openDatabase = DroidDB_openDatabase;
|
||||
window.droiddb = new DroidDB();
|
||||
}
|
||||
if (typeof window.openDatabase === "undefined") {
|
||||
setupDroidDB();
|
||||
} else {
|
||||
window.openDatabase_orig = window.openDatabase;
|
||||
window.openDatabase = function(name, version, desc, size){
|
||||
// Some versions of Android will throw a SECURITY_ERR so we need
|
||||
// to catch the exception and seutp our own DB handling.
|
||||
var db = null;
|
||||
try {
|
||||
db = window.openDatabase_orig(name, version, desc, size);
|
||||
}
|
||||
catch (ex) {
|
||||
db = null;
|
||||
}
|
||||
|
||||
if (db == null) {
|
||||
setupDroidDB();
|
||||
return DroidDB_openDatabase(name, version, desc, size);
|
||||
}
|
||||
else {
|
||||
return db;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window.localStorage === "undefined") {
|
||||
navigator.localStorage = window.localStorage = new CupcakeLocalStorage();
|
||||
PhoneGap.waitForInitialization("cupcakeStorage");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,25 @@
|
||||
<!--
|
||||
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>
|
||||
<title></title>
|
||||
<script src="phonegap-1.2.0.js"></script>
|
||||
<script src="cordova-1.5.0.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="PhoneGap" default="jar">
|
||||
<!--
|
||||
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">
|
||||
@@ -90,75 +108,68 @@
|
||||
-->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
|
||||
<target name="check-javascript" depends="build-javascript">
|
||||
<delete dir="assets/lib"/>
|
||||
<mkdir dir="assets/lib"/>
|
||||
<echo file="assets/lib/lint.js">var alert=function(){},device={},Element={},debug={};</echo>
|
||||
<concat destfile="assets/lib/phonegap-lint.js" append="true">
|
||||
<fileset dir="assets/lib">
|
||||
<include name="lint.js" />
|
||||
</fileset>
|
||||
<fileset dir="assets/www">
|
||||
<include name="phonegap-${version}.js" />
|
||||
</fileset>
|
||||
</concat>
|
||||
|
||||
<exec executable="cmd" os="Windows 7">
|
||||
<arg value="/c"/>
|
||||
<arg value="java"/>
|
||||
<arg value="-cp"/>
|
||||
<arg value="${basedir}/util/js.jar"/>
|
||||
<arg value="org.mozilla.javascript.tools.shell.Main"/>
|
||||
<arg value="${basedir}/util/jslint.js"/>
|
||||
<arg value="${basedir}/js/lib/phonegap-lint.js"/>
|
||||
</exec>
|
||||
<exec executable="java" os="Mac OS X">
|
||||
<arg value="-cp"/>
|
||||
<arg value="../util/js.jar"/>
|
||||
<arg value="org.mozilla.javascript.tools.shell.Main"/>
|
||||
<arg value="../util/jslint.js"/>
|
||||
<arg value="assets/lib/phonegap-lint.js"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<!-- Combine JavaScript files into one phonegap-uncompressed.js file. -->
|
||||
<target name="build-javascript">
|
||||
<!-- Combine JavaScript files into one cordova-uncompressed.js file. -->
|
||||
<target name="build-javascript" depends="clean">
|
||||
|
||||
<!-- Clean up existing files -->
|
||||
<!--<delete file="assets/www/phonegap_${version}.js"/>-->
|
||||
<!--<delete file="assets/www/cordova_${version}.js"/>-->
|
||||
|
||||
<!-- Create uncompressed JS file -->
|
||||
<concat destfile="assets/www/phonegap-${version}.js">
|
||||
<fileset dir="assets/js" includes="phonegap.js.base" />
|
||||
<fileset dir="assets/js" includes="*.js" />
|
||||
<concat destfile="assets/www/cordova-${version}.js">
|
||||
<filelist dir="assets/js" files="cordova.android.js"/>
|
||||
</concat>
|
||||
|
||||
<!-- update project files to reference phonegap-x.x.x.min.js -->
|
||||
<replaceregexp match="phonegap(.*)\.js" replace="phonegap-${version}.js" byline="true">
|
||||
<!-- 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="phonegapVersion = [\u0022].*[\u0022];" replace='phonegapVersion = ${dblQuote}${version}${dblQuote};' byline="true">
|
||||
<fileset file="src/com/phonegap/Device.java" />
|
||||
<replaceregexp match="cordovaVersion = [\u0022].*[\u0022];" replace='cordovaVersion = ${dblQuote}${version}${dblQuote};' byline="true">
|
||||
<fileset file="src/org/apache/cordova/Device.java" />
|
||||
</replaceregexp>
|
||||
|
||||
<!-- Delete temp file -->
|
||||
<!--<delete file="assets/www/phonegap-tmp.js"/>-->
|
||||
</target>
|
||||
|
||||
<!-- Build PhoneGap jar file that includes all native code, and PhoneGap JS file
|
||||
<!-- 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="phonegap-${version}.jar" basedir="bin/classes" excludes="com/phonegap/R.class,com/phonegap/R$*.class"/>
|
||||
<jar jarfile="cordova-${version}.jar" basedir="bin/classes" excludes="org/apache/cordova/R.class,org/apache/cordova/R$*.class"/>
|
||||
</target>
|
||||
|
||||
<target name="phonegap_debug" depends="build-javascript, debug">
|
||||
<!-- 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="phonegap_release" depends="build-javascript, release">
|
||||
<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>
|
||||
|
||||
BIN
framework/res/drawable-hdpi/icon.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
framework/res/drawable-ldpi/icon.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
framework/res/drawable-mdpi/icon.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 92 KiB |
@@ -1,4 +1,22 @@
|
||||
<?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"
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
<?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.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">PhoneGap</string>
|
||||
<string name="app_name">Cordova</string>
|
||||
<string name="go">Snap</string>
|
||||
</resources>
|
||||
|
||||
37
framework/res/xml/cordova.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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="classicRender" value="true" />
|
||||
</cordova>
|
||||
|
||||
|
||||
|
||||
53
framework/res/xml/plugins.xml
Normal file → Executable file
@@ -1,20 +1,37 @@
|
||||
<?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="com.phonegap.App"/>
|
||||
<plugin name="Geolocation" value="com.phonegap.GeoBroker"/>
|
||||
<plugin name="Device" value="com.phonegap.Device"/>
|
||||
<plugin name="Accelerometer" value="com.phonegap.AccelListener"/>
|
||||
<plugin name="Compass" value="com.phonegap.CompassListener"/>
|
||||
<plugin name="Media" value="com.phonegap.AudioHandler"/>
|
||||
<plugin name="Camera" value="com.phonegap.CameraLauncher"/>
|
||||
<plugin name="Contacts" value="com.phonegap.ContactManager"/>
|
||||
<plugin name="Crypto" value="com.phonegap.CryptoHandler"/>
|
||||
<plugin name="File" value="com.phonegap.FileUtils"/>
|
||||
<plugin name="Network Status" value="com.phonegap.NetworkManager"/>
|
||||
<plugin name="Notification" value="com.phonegap.Notification"/>
|
||||
<plugin name="Storage" value="com.phonegap.Storage"/>
|
||||
<plugin name="Temperature" value="com.phonegap.TempListener"/>
|
||||
<plugin name="FileTransfer" value="com.phonegap.FileTransfer"/>
|
||||
<plugin name="Capture" value="com.phonegap.Capture"/>
|
||||
<plugin name="Battery" value="com.phonegap.BatteryListener"/>
|
||||
</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="Network Status" 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"/>
|
||||
</plugins>
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
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 PhoneGap 1.0.
|
||||
*/
|
||||
if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
|
||||
JSONObject res = null;
|
||||
try {
|
||||
res = new JSONObject();
|
||||
res.put("code", NOT_SUPPORTED_ERROR);
|
||||
res.put("message", "Contacts are not supported in Android 1.X devices");
|
||||
} catch (JSONException e) {
|
||||
// This should never happen
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
return new PluginResult(PluginResult.Status.ERROR, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, "navigator.contacts.cast");
|
||||
}
|
||||
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
|
||||
JSONObject r = new JSONObject();
|
||||
r.put("code", UNKNOWN_ERROR);
|
||||
return new PluginResult(PluginResult.Status.ERROR, r);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
public class CryptoHandler extends Plugin {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CryptoHandler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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("encrypt")) {
|
||||
this.encrypt(args.getString(0), args.getString(1));
|
||||
}
|
||||
else if (action.equals("decrypt")) {
|
||||
this.decrypt(args.getString(0), args.getString(1));
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
public void encrypt(String pass, String text) {
|
||||
try {
|
||||
String encrypted = SimpleCrypto.encrypt(pass,text);
|
||||
// TODO: Why not just return text now?
|
||||
this.sendJavascript("Crypto.gotCryptedString('" + text + "')");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void decrypt(String pass, String text) {
|
||||
try {
|
||||
String decrypted = SimpleCrypto.decrypt(pass,text);
|
||||
this.sendJavascript("Crypto.gotPlainString('" + text + "')");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import android.provider.Settings;
|
||||
|
||||
public class Device extends Plugin {
|
||||
|
||||
public static String phonegapVersion = "1.2.0"; // PhoneGap version
|
||||
public static String platform = "Android"; // Device OS
|
||||
public static String uuid; // Device UUID
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public Device() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(PhonegapActivity ctx) {
|
||||
super.setContext(ctx);
|
||||
Device.uuid = getUuid();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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("getDeviceInfo")) {
|
||||
JSONObject r = new JSONObject();
|
||||
r.put("uuid", Device.uuid);
|
||||
r.put("version", this.getOSVersion());
|
||||
r.put("platform", Device.platform);
|
||||
r.put("name", this.getProductName());
|
||||
r.put("phonegap", Device.phonegapVersion);
|
||||
//JSONObject pg = new JSONObject();
|
||||
//pg.put("version", Device.phonegapVersion);
|
||||
//r.put("phonegap", pg);
|
||||
return new PluginResult(status, r);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
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("getDeviceInfo")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get the OS name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPlatform() {
|
||||
return Device.platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the device's Universally Unique Identifier (UUID).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getUuid() {
|
||||
String uuid = Settings.Secure.getString(this.ctx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PhoneGap version.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPhonegapVersion() {
|
||||
return Device.phonegapVersion;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
String model = android.os.Build.MODEL;
|
||||
return model;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
String productname = android.os.Build.PRODUCT;
|
||||
return productname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OS version.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getOSVersion() {
|
||||
String osversion = android.os.Build.VERSION.RELEASE;
|
||||
return osversion;
|
||||
}
|
||||
|
||||
public String getSDKVersion() {
|
||||
String sdkversion = android.os.Build.VERSION.SDK;
|
||||
return sdkversion;
|
||||
}
|
||||
|
||||
|
||||
public String getTimeZoneID() {
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
return(tz.getID());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.webkit.CookieManager;
|
||||
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
public class FileTransfer extends Plugin {
|
||||
|
||||
private static final String LOG_TAG = "FileUploader";
|
||||
private static final String LINE_START = "--";
|
||||
private static final String LINE_END = "\r\n";
|
||||
private static final String BOUNDRY = "*****";
|
||||
|
||||
public static int FILE_NOT_FOUND_ERR = 1;
|
||||
public static int INVALID_URL_ERR = 2;
|
||||
public static int CONNECTION_ERR = 3;
|
||||
|
||||
private SSLSocketFactory defaultSSLSocketFactory = null;
|
||||
private HostnameVerifier defaultHostnameVerifier = null;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
String file = null;
|
||||
String server = null;
|
||||
try {
|
||||
file = args.getString(0);
|
||||
server = args.getString(1);
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Missing filename or server name");
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing filename or server name");
|
||||
}
|
||||
|
||||
// Setup the options
|
||||
String fileKey = null;
|
||||
String fileName = null;
|
||||
String mimeType = null;
|
||||
|
||||
fileKey = getArgument(args, 2, "file");
|
||||
fileName = getArgument(args, 3, "image.jpg");
|
||||
mimeType = getArgument(args, 4, "image/jpeg");
|
||||
|
||||
try {
|
||||
JSONObject params = args.optJSONObject(5);
|
||||
boolean trustEveryone = args.optBoolean(6);
|
||||
boolean chunkedMode = args.getBoolean(7);
|
||||
|
||||
if (action.equals("upload")) {
|
||||
FileUploadResult r = upload(file, server, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode);
|
||||
Log.d(LOG_TAG, "****** About to return a result from upload");
|
||||
return new PluginResult(PluginResult.Status.OK, r.toJSONObject());
|
||||
} else {
|
||||
return new PluginResult(PluginResult.Status.INVALID_ACTION);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
JSONObject error = createFileUploadError(FILE_NOT_FOUND_ERR);
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
JSONObject error = createFileUploadError(INVALID_URL_ERR);
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
|
||||
} catch (SSLException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
Log.d(LOG_TAG, "Got my ssl exception!!!");
|
||||
JSONObject error = createFileUploadError(CONNECTION_ERR);
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
|
||||
} catch (IOException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
JSONObject error = createFileUploadError(CONNECTION_ERR);
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
// always verify the host - don't check for certificate
|
||||
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This function will install a trust manager that will blindly trust all SSL
|
||||
* certificates. The reason this code is being added is to enable developers
|
||||
* to do development using self signed SSL certificates on their web server.
|
||||
*
|
||||
* The standard HttpsURLConnection class will throw an exception on self
|
||||
* signed certificates if this code is not run.
|
||||
*/
|
||||
private void trustAllHosts() {
|
||||
// Create a trust manager that does not validate certificate chains
|
||||
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return new java.security.cert.X509Certificate[] {};
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] chain,
|
||||
String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] chain,
|
||||
String authType) throws CertificateException {
|
||||
}
|
||||
} };
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
try {
|
||||
// Backup the current SSL socket factory
|
||||
defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
|
||||
// Install our all trusting manager
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
sc.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error object based on the passed in errorCode
|
||||
* @param errorCode the error
|
||||
* @return JSONObject containing the error
|
||||
*/
|
||||
private JSONObject createFileUploadError(int errorCode) {
|
||||
JSONObject error = null;
|
||||
try {
|
||||
error = new JSONObject();
|
||||
error.put("code", errorCode);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to read a parameter from the list of JSON args.
|
||||
* @param args the args passed to the Plugin
|
||||
* @param position the position to retrieve the arg from
|
||||
* @param defaultString the default to be used if the arg does not exist
|
||||
* @return String with the retrieved value
|
||||
*/
|
||||
private String getArgument(JSONArray args, int position, String defaultString) {
|
||||
String arg = defaultString;
|
||||
if(args.length() >= position) {
|
||||
arg = args.optString(position);
|
||||
if (arg == null || "null".equals(arg)) {
|
||||
arg = defaultString;
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads the specified file to the server URL provided using an HTTP
|
||||
* multipart request.
|
||||
* @param file Full path of the file on the file system
|
||||
* @param server URL of the server to receive the file
|
||||
* @param fileKey Name of file request parameter
|
||||
* @param fileName File name to be used on server
|
||||
* @param mimeType Describes file content type
|
||||
* @param params key:value pairs of user-defined parameters
|
||||
* @return FileUploadResult containing result of upload request
|
||||
*/
|
||||
public FileUploadResult upload(String file, String server, final String fileKey, final String fileName,
|
||||
final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException {
|
||||
// Create return object
|
||||
FileUploadResult result = new FileUploadResult();
|
||||
|
||||
// Get a input stream of the file on the phone
|
||||
InputStream fileInputStream = getPathFromUri(file);
|
||||
|
||||
HttpURLConnection conn = null;
|
||||
DataOutputStream dos = null;
|
||||
|
||||
int bytesRead, bytesAvailable, bufferSize;
|
||||
long totalBytes;
|
||||
byte[] buffer;
|
||||
int maxBufferSize = 8096;
|
||||
|
||||
//------------------ CLIENT REQUEST
|
||||
// open a URL connection to the server
|
||||
URL url = new URL(server);
|
||||
|
||||
// Open a HTTP connection to the URL based on protocol
|
||||
if (url.getProtocol().toLowerCase().equals("https")) {
|
||||
// Using standard HTTPS connection. Will not allow self signed certificate
|
||||
if (!trustEveryone) {
|
||||
conn = (HttpsURLConnection) url.openConnection();
|
||||
}
|
||||
// Use our HTTPS connection that blindly trusts everyone.
|
||||
// This should only be used in debug environments
|
||||
else {
|
||||
// Setup the HTTPS connection class to trust everyone
|
||||
trustAllHosts();
|
||||
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
|
||||
// Save the current hostnameVerifier
|
||||
defaultHostnameVerifier = https.getHostnameVerifier();
|
||||
// Setup the connection not to verify hostnames
|
||||
https.setHostnameVerifier(DO_NOT_VERIFY);
|
||||
conn = https;
|
||||
}
|
||||
}
|
||||
// Return a standard HTTP connection
|
||||
else {
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
}
|
||||
|
||||
// Allow Inputs
|
||||
conn.setDoInput(true);
|
||||
|
||||
// Allow Outputs
|
||||
conn.setDoOutput(true);
|
||||
|
||||
// Don't use a cached copy.
|
||||
conn.setUseCaches(false);
|
||||
|
||||
// Use a post method.
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Connection", "Keep-Alive");
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY);
|
||||
|
||||
// Set the cookies on the response
|
||||
String cookie = CookieManager.getInstance().getCookie(server);
|
||||
if (cookie != null) {
|
||||
conn.setRequestProperty("Cookie", cookie);
|
||||
}
|
||||
|
||||
// Should set this up as an option
|
||||
if (chunkedMode) {
|
||||
conn.setChunkedStreamingMode(maxBufferSize);
|
||||
}
|
||||
|
||||
dos = new DataOutputStream( conn.getOutputStream() );
|
||||
|
||||
// Send any extra parameters
|
||||
try {
|
||||
for (Iterator iter = params.keys(); iter.hasNext();) {
|
||||
Object key = iter.next();
|
||||
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
|
||||
dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\";");
|
||||
dos.writeBytes(LINE_END + LINE_END);
|
||||
dos.write(params.getString(key.toString()).getBytes());
|
||||
dos.writeBytes(LINE_END);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
|
||||
dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"" + fileName +"\"" + LINE_END);
|
||||
dos.writeBytes("Content-Type: " + mimeType + LINE_END);
|
||||
dos.writeBytes(LINE_END);
|
||||
|
||||
// create a buffer of maximum size
|
||||
bytesAvailable = fileInputStream.available();
|
||||
bufferSize = Math.min(bytesAvailable, maxBufferSize);
|
||||
buffer = new byte[bufferSize];
|
||||
|
||||
// read file and write it into form...
|
||||
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
|
||||
totalBytes = 0;
|
||||
|
||||
while (bytesRead > 0) {
|
||||
totalBytes += bytesRead;
|
||||
result.setBytesSent(totalBytes);
|
||||
dos.write(buffer, 0, bufferSize);
|
||||
bytesAvailable = fileInputStream.available();
|
||||
bufferSize = Math.min(bytesAvailable, maxBufferSize);
|
||||
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
|
||||
}
|
||||
|
||||
// send multipart form data necesssary after file data...
|
||||
dos.writeBytes(LINE_END);
|
||||
dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END);
|
||||
|
||||
// close streams
|
||||
fileInputStream.close();
|
||||
dos.flush();
|
||||
dos.close();
|
||||
|
||||
//------------------ read the SERVER RESPONSE
|
||||
StringBuffer responseString = new StringBuffer("");
|
||||
DataInputStream inStream;
|
||||
try {
|
||||
inStream = new DataInputStream ( conn.getInputStream() );
|
||||
} catch(FileNotFoundException e) {
|
||||
throw new IOException("Received error from server");
|
||||
}
|
||||
|
||||
String line;
|
||||
while (( line = inStream.readLine()) != null) {
|
||||
responseString.append(line);
|
||||
}
|
||||
Log.d(LOG_TAG, "got response from server");
|
||||
Log.d(LOG_TAG, responseString.toString());
|
||||
|
||||
// send request and retrieve response
|
||||
result.setResponseCode(conn.getResponseCode());
|
||||
result.setResponse(responseString.toString());
|
||||
|
||||
inStream.close();
|
||||
conn.disconnect();
|
||||
|
||||
// Revert back to the proper verifier and socket factories
|
||||
if (trustEveryone && url.getProtocol().toLowerCase().equals("https")) {
|
||||
((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier);
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an input stream based on file path or content:// uri
|
||||
*
|
||||
* @param path
|
||||
* @return an input stream
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private InputStream getPathFromUri(String path) throws FileNotFoundException {
|
||||
if (path.startsWith("content:")) {
|
||||
Uri uri = Uri.parse(path);
|
||||
return ctx.getContentResolver().openInputStream(uri);
|
||||
}
|
||||
else if (path.startsWith("file://")) {
|
||||
return new FileInputStream(path.substring(7));
|
||||
}
|
||||
else {
|
||||
return new FileInputStream(path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
|
||||
public class HttpHandler {
|
||||
|
||||
protected Boolean get(String url, String file)
|
||||
{
|
||||
HttpEntity entity = getHttpEntity(url);
|
||||
try {
|
||||
writeToDisk(entity, file);
|
||||
} catch (Exception e) { e.printStackTrace(); return false; }
|
||||
try {
|
||||
entity.consumeContent();
|
||||
} catch (Exception e) { e.printStackTrace(); return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
private HttpEntity getHttpEntity(String url)
|
||||
/**
|
||||
* get the http entity at a given url
|
||||
*/
|
||||
{
|
||||
HttpEntity entity=null;
|
||||
try {
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient();
|
||||
HttpGet httpget = new HttpGet(url);
|
||||
HttpResponse response = httpclient.execute(httpget);
|
||||
entity = response.getEntity();
|
||||
} catch (Exception e) { e.printStackTrace(); return null; }
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void writeToDisk(HttpEntity entity, String file) throws EOFException
|
||||
/**
|
||||
* writes a HTTP entity to the specified filename and location on disk
|
||||
*/
|
||||
{
|
||||
int i=0;
|
||||
String FilePath="/sdcard/" + file;
|
||||
try {
|
||||
InputStream in = entity.getContent();
|
||||
byte buff[] = new byte[1024];
|
||||
FileOutputStream out=
|
||||
new FileOutputStream(FilePath);
|
||||
do {
|
||||
int numread = in.read(buff);
|
||||
if (numread <= 0)
|
||||
break;
|
||||
out.write(buff, 0, numread);
|
||||
i++;
|
||||
} while (true);
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Vibrator;
|
||||
|
||||
/**
|
||||
* This class provides access to notifications on the device.
|
||||
*/
|
||||
public class Notification extends Plugin {
|
||||
|
||||
public int confirmResult = -1;
|
||||
public ProgressDialog spinnerDialog = null;
|
||||
public ProgressDialog progressDialog = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public Notification() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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("beep")) {
|
||||
this.beep(args.getLong(0));
|
||||
}
|
||||
else if (action.equals("vibrate")) {
|
||||
this.vibrate(args.getLong(0));
|
||||
}
|
||||
else if (action.equals("alert")) {
|
||||
this.alert(args.getString(0),args.getString(1),args.getString(2), callbackId);
|
||||
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||
r.setKeepCallback(true);
|
||||
return r;
|
||||
}
|
||||
else if (action.equals("confirm")) {
|
||||
this.confirm(args.getString(0),args.getString(1),args.getString(2), callbackId);
|
||||
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||
r.setKeepCallback(true);
|
||||
return r;
|
||||
}
|
||||
else if (action.equals("activityStart")) {
|
||||
this.activityStart(args.getString(0),args.getString(1));
|
||||
}
|
||||
else if (action.equals("activityStop")) {
|
||||
this.activityStop();
|
||||
}
|
||||
else if (action.equals("progressStart")) {
|
||||
this.progressStart(args.getString(0),args.getString(1));
|
||||
}
|
||||
else if (action.equals("progressValue")) {
|
||||
this.progressValue(args.getInt(0));
|
||||
}
|
||||
else if (action.equals("progressStop")) {
|
||||
this.progressStop();
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
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("alert")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("confirm")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("activityStart")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("activityStop")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("progressStart")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("progressValue")) {
|
||||
return true;
|
||||
}
|
||||
else if (action.equals("progressStop")) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Beep plays the default notification ringtone.
|
||||
*
|
||||
* @param count Number of times to play notification
|
||||
*/
|
||||
public void beep(long count) {
|
||||
Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
Ringtone notification = RingtoneManager.getRingtone(this.ctx, ringtone);
|
||||
|
||||
// If phone is not set to silent mode
|
||||
if (notification != null) {
|
||||
for (long i = 0; i < count; ++i) {
|
||||
notification.play();
|
||||
long timeout = 5000;
|
||||
while (notification.isPlaying() && (timeout > 0)) {
|
||||
timeout = timeout - 100;
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vibrates the device for the specified amount of time.
|
||||
*
|
||||
* @param time Time to vibrate in ms.
|
||||
*/
|
||||
public void vibrate(long time){
|
||||
// Start the vibration, 0 defaults to half a second.
|
||||
if (time == 0) {
|
||||
time = 500;
|
||||
}
|
||||
Vibrator vibrator = (Vibrator) this.ctx.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
vibrator.vibrate(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and shows a native Android alert with given Strings
|
||||
* @param message The message the alert should display
|
||||
* @param title The title of the alert
|
||||
* @param buttonLabel The label of the button
|
||||
* @param callbackId The callback id
|
||||
*/
|
||||
public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) {
|
||||
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
final Notification notification = this;
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx);
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle(title);
|
||||
dlg.setCancelable(false);
|
||||
dlg.setPositiveButton(buttonLabel,
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
notification.success(new PluginResult(PluginResult.Status.OK, 0), callbackId);
|
||||
}
|
||||
});
|
||||
dlg.create();
|
||||
dlg.show();
|
||||
};
|
||||
};
|
||||
this.ctx.runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and shows a native Android confirm dialog with given title, message, buttons.
|
||||
* This dialog only shows up to 3 buttons. Any labels after that will be ignored.
|
||||
* The index of the button pressed will be returned to the JavaScript callback identified by callbackId.
|
||||
*
|
||||
* @param message The message the dialog should display
|
||||
* @param title The title of the dialog
|
||||
* @param buttonLabels A comma separated list of button labels (Up to 3 buttons)
|
||||
* @param callbackId The callback id
|
||||
*/
|
||||
public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) {
|
||||
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
final Notification notification = this;
|
||||
final String[] fButtons = buttonLabels.split(",");
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx);
|
||||
dlg.setMessage(message);
|
||||
dlg.setTitle(title);
|
||||
dlg.setCancelable(false);
|
||||
|
||||
// First button
|
||||
if (fButtons.length > 0) {
|
||||
dlg.setPositiveButton(fButtons[0],
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
notification.success(new PluginResult(PluginResult.Status.OK, 1), callbackId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Second button
|
||||
if (fButtons.length > 1) {
|
||||
dlg.setNeutralButton(fButtons[1],
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
notification.success(new PluginResult(PluginResult.Status.OK, 2), callbackId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Third button
|
||||
if (fButtons.length > 2) {
|
||||
dlg.setNegativeButton(fButtons[2],
|
||||
new AlertDialog.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
notification.success(new PluginResult(PluginResult.Status.OK, 3), callbackId);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
dlg.create();
|
||||
dlg.show();
|
||||
};
|
||||
};
|
||||
this.ctx.runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the spinner.
|
||||
*
|
||||
* @param title Title of the dialog
|
||||
* @param message The message of the dialog
|
||||
*/
|
||||
public synchronized void activityStart(final String title, final String message) {
|
||||
if (this.spinnerDialog != null) {
|
||||
this.spinnerDialog.dismiss();
|
||||
this.spinnerDialog = null;
|
||||
}
|
||||
final Notification notification = this;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
notification.spinnerDialog = ProgressDialog.show(ctx, title , message, true, true,
|
||||
new DialogInterface.OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
notification.spinnerDialog = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
this.ctx.runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop spinner.
|
||||
*/
|
||||
public synchronized void activityStop() {
|
||||
if (this.spinnerDialog != null) {
|
||||
this.spinnerDialog.dismiss();
|
||||
this.spinnerDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the progress dialog.
|
||||
*
|
||||
* @param title Title of the dialog
|
||||
* @param message The message of the dialog
|
||||
*/
|
||||
public synchronized void progressStart(final String title, final String message) {
|
||||
if (this.progressDialog != null) {
|
||||
this.progressDialog.dismiss();
|
||||
this.progressDialog = null;
|
||||
}
|
||||
final Notification notification = this;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
notification.progressDialog = new ProgressDialog(ctx);
|
||||
notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
notification.progressDialog.setTitle(title);
|
||||
notification.progressDialog.setMessage(message);
|
||||
notification.progressDialog.setCancelable(true);
|
||||
notification.progressDialog.setMax(100);
|
||||
notification.progressDialog.setProgress(0);
|
||||
notification.progressDialog.setOnCancelListener(
|
||||
new DialogInterface.OnCancelListener() {
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
notification.progressDialog = null;
|
||||
}
|
||||
});
|
||||
notification.progressDialog.show();
|
||||
}
|
||||
};
|
||||
this.ctx.runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value of progress bar.
|
||||
*
|
||||
* @param value 0-100
|
||||
*/
|
||||
public synchronized void progressValue(int value) {
|
||||
if (this.progressDialog != null) {
|
||||
this.progressDialog.setProgress(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop progress dialog.
|
||||
*/
|
||||
public synchronized void progressStop() {
|
||||
if (this.progressDialog != null) {
|
||||
this.progressDialog.dismiss();
|
||||
this.progressDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Code originally found on Android Snippets
|
||||
* Contributed to snippets Ferenc Hechler
|
||||
* Copyright (c) 2009 Ferenc Hechler
|
||||
*/
|
||||
|
||||
package com.phonegap;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class SimpleCrypto {
|
||||
|
||||
public static String encrypt(String seed, String cleartext) throws Exception {
|
||||
byte[] rawKey = getRawKey(seed.getBytes());
|
||||
byte[] result = encrypt(rawKey, cleartext.getBytes());
|
||||
return toHex(result);
|
||||
}
|
||||
|
||||
public static String decrypt(String seed, String encrypted) throws Exception {
|
||||
byte [] rawKey = getRawKey(seed.getBytes());
|
||||
byte [] enc = toByte(encrypted);
|
||||
byte [] result = decrypt(rawKey, enc);
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
public static byte[] getRawKey(byte [] seed) throws Exception {
|
||||
KeyGenerator kgen = KeyGenerator.getInstance("AES");
|
||||
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
|
||||
sr.setSeed(seed);
|
||||
kgen.init(128, sr);
|
||||
SecretKey skey = kgen.generateKey();
|
||||
byte[] raw = skey.getEncoded();
|
||||
return raw;
|
||||
}
|
||||
|
||||
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
|
||||
byte[] encrypted = cipher.doFinal(clear);
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
|
||||
byte[] decrypted = cipher.doFinal(encrypted);
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
public static String toHex(String txt)
|
||||
{
|
||||
return toHex(txt.getBytes());
|
||||
}
|
||||
|
||||
public static String fromHex(String hex)
|
||||
{
|
||||
return new String(toByte(hex));
|
||||
}
|
||||
|
||||
public static byte[] toByte(String hexString) {
|
||||
int len = hexString.length()/2;
|
||||
byte[] result = new byte[len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String toHex(byte[] buf) {
|
||||
if (buf == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
StringBuffer result = new StringBuffer(2*buf.length);
|
||||
for (int i = 0; i < buf.length; i++)
|
||||
{
|
||||
appendHex(result, buf[i]);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private final static String HEX = "01234567890ABCDEF";
|
||||
|
||||
private static void appendHex(StringBuffer sb, byte b)
|
||||
{
|
||||
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class StandAlone extends DroidGap {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
super.loadUrl("file:///android_asset/www/index.html");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import android.webkit.WebSettings;
|
||||
|
||||
public class WebViewReflect {
|
||||
private static Method mWebSettings_setDatabaseEnabled;
|
||||
private static Method mWebSettings_setDatabasePath;
|
||||
private static Method mWebSettings_setDomStorageEnabled;
|
||||
private static Method mWebSettings_setGeolocationEnabled;
|
||||
|
||||
static
|
||||
{
|
||||
checkCompatibility();
|
||||
}
|
||||
|
||||
private static void setDatabaseEnabled(boolean e) throws IOException {
|
||||
try
|
||||
{
|
||||
mWebSettings_setDatabaseEnabled.invoke(e);
|
||||
}
|
||||
catch (InvocationTargetException ite) {
|
||||
/* unpack original exception when possible */
|
||||
Throwable cause = ite.getCause();
|
||||
if (cause instanceof IOException) {
|
||||
throw (IOException) cause;
|
||||
} else if (cause instanceof RuntimeException) {
|
||||
throw (RuntimeException) cause;
|
||||
} else if (cause instanceof Error) {
|
||||
throw (Error) cause;
|
||||
} else {
|
||||
/* unexpected checked exception; wrap and re-throw */
|
||||
throw new RuntimeException(ite);
|
||||
}
|
||||
} catch (IllegalAccessException ie) {
|
||||
System.err.println("unexpected " + ie);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void checkCompatibility() {
|
||||
try {
|
||||
mWebSettings_setDatabaseEnabled = WebSettings.class.getMethod(
|
||||
"setDatabaseEnabled", new Class[] { boolean.class } );
|
||||
mWebSettings_setDatabasePath = WebSettings.class.getMethod(
|
||||
"setDatabasePath", new Class[] { String.class });
|
||||
mWebSettings_setDomStorageEnabled = WebSettings.class.getMethod(
|
||||
"setDomStorageEnabled", new Class[] { boolean.class });
|
||||
mWebSettings_setGeolocationEnabled = WebSettings.class.getMethod(
|
||||
"setGeolocationEnabled", new Class[] { boolean.class });
|
||||
/* success, this is a newer device */
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
/* failure, must be older device */
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStorage(WebSettings setting, boolean enable, String path) {
|
||||
if (mWebSettings_setDatabaseEnabled != null) {
|
||||
/* feature is supported */
|
||||
try {
|
||||
mWebSettings_setDatabaseEnabled.invoke(setting, enable);
|
||||
mWebSettings_setDatabasePath.invoke(setting, path);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
/* feature not supported, do something else */
|
||||
}
|
||||
}
|
||||
public static void setGeolocationEnabled(WebSettings setting, boolean enable) {
|
||||
if (mWebSettings_setGeolocationEnabled != null) {
|
||||
/* feature is supported */
|
||||
try {
|
||||
mWebSettings_setGeolocationEnabled.invoke(setting, enable);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
/* feature not supported, do something else */
|
||||
System.out.println("Native Geolocation not supported - we're ok");
|
||||
}
|
||||
}
|
||||
public static void setDomStorage(WebSettings setting)
|
||||
{
|
||||
if(mWebSettings_setDomStorageEnabled != null)
|
||||
{
|
||||
/* feature is supported */
|
||||
try {
|
||||
mWebSettings_setDomStorageEnabled.invoke(setting, true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
/* feature not supported, do something else */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,97 +1,27 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap.api;
|
||||
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
|
||||
|
||||
import org.json.JSONArray;
|
||||
import android.content.Intent;
|
||||
import android.webkit.WebView;
|
||||
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 interface IPlugin {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
PluginResult execute(String action, JSONArray args, String callbackId);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Sets the context of the Plugin. This can then be used to do things like
|
||||
* get file paths associated with the Activity.
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
void setContext(PhonegapActivity ctx);
|
||||
|
||||
/**
|
||||
* Sets the main View of the application, this is the WebView within which
|
||||
* a PhoneGap app runs.
|
||||
*
|
||||
* @param webView The PhoneGap WebView
|
||||
*/
|
||||
void setView(WebView webView);
|
||||
|
||||
/**
|
||||
* Called when the system is about to start resuming a previous activity.
|
||||
*
|
||||
* @param multitasking Flag indicating if multitasking is turned on for app
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void onResume(boolean multitasking);
|
||||
|
||||
/**
|
||||
* Called when the activity receives a new intent.
|
||||
*/
|
||||
void onNewIntent(Intent intent);
|
||||
|
||||
/**
|
||||
* The final call you receive before your activity is destroyed.
|
||||
*/
|
||||
void onDestroy();
|
||||
|
||||
/**
|
||||
* 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 data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
|
||||
*/
|
||||
void onActivityResult(int requestCode, int resultCode, Intent intent);
|
||||
|
||||
/**
|
||||
* By specifying a <url-filter> in plugins.xml you can map a URL (using startsWith atm) to this method.
|
||||
*
|
||||
* @param url The URL that is trying to be loaded in the PhoneGap webview.
|
||||
* @return Return true to prevent the URL from loading. Default is false.
|
||||
*/
|
||||
boolean onOverrideUrlLoading(String url);
|
||||
}
|
||||
public interface IPlugin extends org.apache.cordova.api.IPlugin {
|
||||
}
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap.api;
|
||||
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
|
||||
|
||||
import android.util.Log;
|
||||
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.
|
||||
@@ -15,209 +24,5 @@ import android.util.Log;
|
||||
* 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 {
|
||||
|
||||
public static final int VERBOSE = Log.VERBOSE;
|
||||
public static final int DEBUG = Log.DEBUG;
|
||||
public static final int INFO = Log.INFO;
|
||||
public static final int WARN = Log.WARN;
|
||||
public static final int ERROR = Log.ERROR;
|
||||
|
||||
// Current log level
|
||||
public static int LOGLEVEL = Log.ERROR;
|
||||
|
||||
/**
|
||||
* Set the current log level.
|
||||
*
|
||||
* @param logLevel
|
||||
*/
|
||||
public static void setLogLevel(int logLevel) {
|
||||
LOGLEVEL = logLevel;
|
||||
Log.i("PhoneGapLog", "Changing log level to " + logLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current log level.
|
||||
*
|
||||
* @param logLevel
|
||||
*/
|
||||
public static void setLogLevel(String logLevel) {
|
||||
if ("VERBOSE".equals(logLevel)) LOGLEVEL = VERBOSE;
|
||||
else if ("DEBUG".equals(logLevel)) LOGLEVEL = DEBUG;
|
||||
else if ("INFO".equals(logLevel)) LOGLEVEL = INFO;
|
||||
else if ("WARN".equals(logLevel)) LOGLEVEL = WARN;
|
||||
else if ("ERROR".equals(logLevel)) LOGLEVEL = ERROR;
|
||||
Log.i("PhoneGapLog", "Changing log level to " + logLevel + "(" + LOGLEVEL + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if log level will be logged
|
||||
*
|
||||
* @param logLevel
|
||||
* @return
|
||||
*/
|
||||
public static boolean isLoggable(int logLevel) {
|
||||
return (logLevel >= LOGLEVEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbose log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
*/
|
||||
public static void v(String tag, String s) {
|
||||
if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
*/
|
||||
public static void d(String tag, String s) {
|
||||
if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Info log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
*/
|
||||
public static void i(String tag, String s) {
|
||||
if (LOG.INFO >= LOGLEVEL) Log.i(tag, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
*/
|
||||
public static void w(String tag, String s) {
|
||||
if (LOG.WARN >= LOGLEVEL) Log.w(tag, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
*/
|
||||
public static void e(String tag, String s) {
|
||||
if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbose log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param e
|
||||
*/
|
||||
public static void v(String tag, String s, Throwable e) {
|
||||
if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param e
|
||||
*/
|
||||
public static void d(String tag, String s, Throwable e) {
|
||||
if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Info log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param e
|
||||
*/
|
||||
public static void i(String tag, String s, Throwable e) {
|
||||
if (LOG.INFO >= LOGLEVEL) Log.i(tag, s, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param e
|
||||
*/
|
||||
public static void w(String tag, String s, Throwable e) {
|
||||
if (LOG.WARN >= LOGLEVEL) Log.w(tag, s, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error log message.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param e
|
||||
*/
|
||||
public static void e(String tag, String s, Throwable e) {
|
||||
if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verbose log message with printf formatting.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param args
|
||||
*/
|
||||
public static void v(String tag, String s, Object... args) {
|
||||
if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, String.format(s, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug log message with printf formatting.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param args
|
||||
*/
|
||||
public static void d(String tag, String s, Object... args) {
|
||||
if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, String.format(s, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Info log message with printf formatting.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param args
|
||||
*/
|
||||
public static void i(String tag, String s, Object... args) {
|
||||
if (LOG.INFO >= LOGLEVEL) Log.i(tag, String.format(s, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning log message with printf formatting.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param args
|
||||
*/
|
||||
public static void w(String tag, String s, Object... args) {
|
||||
if (LOG.WARN >= LOGLEVEL) Log.w(tag, String.format(s, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Error log message with printf formatting.
|
||||
*
|
||||
* @param tag
|
||||
* @param s
|
||||
* @param args
|
||||
*/
|
||||
public static void e(String tag, String s, Object... args) {
|
||||
if (LOG.ERROR >= LOGLEVEL) Log.e(tag, String.format(s, args));
|
||||
}
|
||||
|
||||
public class LOG extends org.apache.cordova.api.LOG {
|
||||
}
|
||||
|
||||
@@ -1,57 +1,28 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
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 android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* The Phonegap activity abstract class that is extended by DroidGap.
|
||||
* It is used to isolate plugin development, and remove dependency on entire Phonegap library.
|
||||
* The Cordova activity abstract class that is extended by DroidGap.
|
||||
* It is used to isolate plugin development, and remove dependency on entire Cordova library.
|
||||
*/
|
||||
public abstract class PhonegapActivity extends Activity {
|
||||
|
||||
/**
|
||||
* Add a class that implements a service.
|
||||
*
|
||||
* @param serviceType
|
||||
* @param className
|
||||
*/
|
||||
abstract public void addService(String serviceType, String className);
|
||||
|
||||
/**
|
||||
* Send JavaScript statement back to JavaScript.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
abstract public void sendJavascript(String statement);
|
||||
|
||||
/**
|
||||
* Launch an activity for which you would like a result when it finished. When this activity exits,
|
||||
* your onActivityResult() method will be called.
|
||||
*
|
||||
* @param command The command object
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Load the specified URL in the PhoneGap webview.
|
||||
*
|
||||
* @param url The URL to load.
|
||||
*/
|
||||
abstract public void loadUrl(String url);
|
||||
public abstract class PhonegapActivity extends Activity implements org.apache.cordova.api.CordovaInterface {
|
||||
}
|
||||
|
||||
@@ -1,190 +1,27 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
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;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.webkit.WebView;
|
||||
|
||||
/**
|
||||
* Plugin interface must be implemented by any plugin classes.
|
||||
*
|
||||
* The execute method is called by the PluginManager.
|
||||
*/
|
||||
public abstract class Plugin implements IPlugin {
|
||||
|
||||
public String id;
|
||||
public WebView webView; // WebView object
|
||||
public PhonegapActivity ctx; // PhonegapActivity object
|
||||
|
||||
/**
|
||||
* 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 abstract PluginResult execute(String action, JSONArray args, String callbackId);
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context of the Plugin. 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(PhonegapActivity ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main View of the application, this is the WebView within which
|
||||
* a PhoneGap app runs.
|
||||
*
|
||||
* @param webView The PhoneGap WebView
|
||||
*/
|
||||
public void setView(WebView webView) {
|
||||
this.webView = webView;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 receives a new intent.
|
||||
*/
|
||||
public void onNewIntent(Intent intent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The final call you receive before your activity is destroyed.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 data 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) {
|
||||
}
|
||||
|
||||
/**
|
||||
* By specifying a <url-filter> in plugins.xml you can map a URL (using startsWith atm) to this method.
|
||||
*
|
||||
* @param url The URL that is trying to be loaded in the PhoneGap webview.
|
||||
* @return Return true to prevent the URL from loading. Default is false.
|
||||
*/
|
||||
public boolean onOverrideUrlLoading(String url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send generic JavaScript statement back to JavaScript.
|
||||
* success(...) and error(...) should be used instead where possible.
|
||||
*
|
||||
* @param statement
|
||||
*/
|
||||
public void sendJavascript(String statement) {
|
||||
this.ctx.sendJavascript(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the JavaScript success callback for this plugin.
|
||||
*
|
||||
* This can be used if the execute code for the plugin is asynchronous meaning
|
||||
* that execute should return null and the callback from the async operation can
|
||||
* call success(...) or error(...)
|
||||
*
|
||||
* @param pluginResult The result to return.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
*/
|
||||
public void success(PluginResult pluginResult, String callbackId) {
|
||||
this.ctx.sendJavascript(pluginResult.toSuccessCallbackString(callbackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
*/
|
||||
public void success(JSONObject message, String callbackId) {
|
||||
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for success callbacks that just returns the Status.OK by default
|
||||
*
|
||||
* @param message The message to add to the success result.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
*/
|
||||
public void success(String message, String callbackId) {
|
||||
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the JavaScript error callback for this plugin.
|
||||
*
|
||||
* @param pluginResult The result to return.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
*/
|
||||
public void error(PluginResult pluginResult, String callbackId) {
|
||||
this.ctx.sendJavascript(pluginResult.toErrorCallbackString(callbackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for error callbacks that just returns the Status.ERROR by default
|
||||
*
|
||||
* @param message The message to add to the error result.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
*/
|
||||
public void error(JSONObject message, String callbackId) {
|
||||
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for error callbacks that just returns the Status.ERROR by default
|
||||
*
|
||||
* @param message The message to add to the error result.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
*/
|
||||
public void error(String message, String callbackId) {
|
||||
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
|
||||
}
|
||||
public abstract class Plugin extends org.apache.cordova.api.Plugin {
|
||||
}
|
||||
|
||||
@@ -1,348 +1,35 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
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 java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import org.apache.cordova.api.CordovaInterface;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
/**
|
||||
* PluginManager is exposed to JavaScript in the PhoneGap WebView.
|
||||
* PluginManager is exposed to JavaScript in the Cordova WebView.
|
||||
*
|
||||
* Calling native plugin code can be done by calling PluginManager.exec(...)
|
||||
* from JavaScript.
|
||||
*/
|
||||
public final class PluginManager {
|
||||
public class PluginManager extends org.apache.cordova.api.PluginManager {
|
||||
|
||||
private HashMap<String, IPlugin> plugins = new HashMap<String,IPlugin>();
|
||||
private HashMap<String, String> services = new HashMap<String,String>();
|
||||
|
||||
private final PhonegapActivity ctx;
|
||||
private final WebView app;
|
||||
|
||||
// Map URL schemes like foo: to plugins that want to handle those schemes
|
||||
// This would allow how all URLs are handled to be offloaded to a plugin
|
||||
protected HashMap<String, String> urlMap = new HashMap<String,String>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param app
|
||||
* @param ctx
|
||||
*/
|
||||
public PluginManager(WebView app, PhonegapActivity ctx) {
|
||||
this.ctx = ctx;
|
||||
this.app = app;
|
||||
this.loadPlugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-init when loading a new HTML page into webview.
|
||||
*/
|
||||
public void reinit() {
|
||||
|
||||
// Stop plugins on current HTML page and discard
|
||||
this.onPause(false);
|
||||
this.onDestroy();
|
||||
this.plugins = new HashMap<String, IPlugin>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load plugins from res/xml/plugins.xml
|
||||
*/
|
||||
public void loadPlugins() {
|
||||
int id = ctx.getResources().getIdentifier("plugins", "xml", ctx.getPackageName());
|
||||
if (id == 0) { pluginConfigurationMissing(); }
|
||||
XmlResourceParser xml = ctx.getResources().getXml(id);
|
||||
int eventType = -1;
|
||||
String pluginClass = "", pluginName = "";
|
||||
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
||||
if (eventType == XmlResourceParser.START_TAG) {
|
||||
String strNode = xml.getName();
|
||||
if (strNode.equals("plugin")) {
|
||||
pluginClass = xml.getAttributeValue(null, "value");
|
||||
pluginName = xml.getAttributeValue(null, "name");
|
||||
//System.out.println("Plugin: "+name+" => "+value);
|
||||
this.addService(pluginName, pluginClass);
|
||||
} else if (strNode.equals("url-filter")) {
|
||||
this.urlMap.put(xml.getAttributeValue(null, "value"), pluginName);
|
||||
}
|
||||
}
|
||||
try {
|
||||
eventType = xml.next();
|
||||
} catch (XmlPullParserException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a request for execution and fulfills it by finding the appropriate
|
||||
* Java class and calling it's execute method.
|
||||
*
|
||||
* PluginManager.exec can be used either synchronously or async. In either case, a JSON encoded
|
||||
* string is returned that will indicate if any errors have occurred when trying to find
|
||||
* or execute the class denoted by the clazz argument.
|
||||
*
|
||||
* @param service String containing the service to run
|
||||
* @param action String containt the action that the class is supposed to perform. This is
|
||||
* passed to the plugin execute method and it is up to the plugin developer
|
||||
* how to deal with it.
|
||||
* @param callbackId String containing the id of the callback that is execute in JavaScript if
|
||||
* this is an async plugin call.
|
||||
* @param args An Array literal string containing any arguments needed in the
|
||||
* plugin execute method.
|
||||
* @param async Boolean indicating whether the calling JavaScript code is expecting an
|
||||
* immediate return value. If true, either PhoneGap.callbackSuccess(...) or
|
||||
* PhoneGap.callbackError(...) is called once the plugin code has executed.
|
||||
*
|
||||
* @return JSON encoded string with a response message and status.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async) {
|
||||
PluginResult cr = null;
|
||||
boolean runAsync = async;
|
||||
try {
|
||||
final JSONArray args = new JSONArray(jsonArgs);
|
||||
final IPlugin plugin = this.getPlugin(service);
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
if (plugin != null) {
|
||||
runAsync = async && !plugin.isSynch(action);
|
||||
if (runAsync) {
|
||||
// Run this on a different thread so that this one can return back to JS
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Call execute on the plugin so that it can do it's thing
|
||||
PluginResult cr = plugin.execute(action, args, callbackId);
|
||||
int status = cr.getStatus();
|
||||
|
||||
// If no result to be sent and keeping callback, then no need to sent back to JavaScript
|
||||
if ((status == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
|
||||
}
|
||||
|
||||
// Check the success (OK, NO_RESULT & !KEEP_CALLBACK)
|
||||
else if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) {
|
||||
ctx.sendJavascript(cr.toSuccessCallbackString(callbackId));
|
||||
}
|
||||
|
||||
// If error
|
||||
else {
|
||||
ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
PluginResult cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
|
||||
ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
return "";
|
||||
} else {
|
||||
// Call execute on the plugin so that it can do it's thing
|
||||
cr = plugin.execute(action, args, callbackId);
|
||||
|
||||
// If no result to be sent and keeping callback, then no need to sent back to JavaScript
|
||||
if ((cr.getStatus() == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
System.out.println("ERROR: "+e.toString());
|
||||
cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
// if async we have already returned at this point unless there was an error...
|
||||
if (runAsync) {
|
||||
if (cr == null) {
|
||||
cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
|
||||
}
|
||||
ctx.sendJavascript(cr.toErrorCallbackString(callbackId));
|
||||
}
|
||||
return ( cr != null ? cr.getJSONString() : "{ status: 0, message: 'all good' }" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class.
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class getClassByName(final String clazz) throws ClassNotFoundException {
|
||||
Class c = null;
|
||||
if (clazz != null) {
|
||||
c = Class.forName(clazz);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interfaces that a class implements and see if it implements the
|
||||
* com.phonegap.api.Plugin interface.
|
||||
*
|
||||
* @param c The class to check the interfaces of.
|
||||
* @return Boolean indicating if the class implements com.phonegap.api.Plugin
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean isPhoneGapPlugin(Class c) {
|
||||
if (c != null) {
|
||||
return com.phonegap.api.Plugin.class.isAssignableFrom(c) || com.phonegap.api.IPlugin.class.isAssignableFrom(c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add plugin to be loaded and cached. This creates an instance of the plugin.
|
||||
* If plugin is already created, then just return it.
|
||||
*
|
||||
* @param className The class to load
|
||||
* @param clazz The class object (must be a class object of the className)
|
||||
* @param callbackId The callback id to use when calling back into JavaScript
|
||||
* @return The plugin
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private IPlugin addPlugin(String pluginName, String className) {
|
||||
try {
|
||||
Class c = getClassByName(className);
|
||||
if (isPhoneGapPlugin(c)) {
|
||||
IPlugin plugin = (IPlugin)c.newInstance();
|
||||
this.plugins.put(className, plugin);
|
||||
plugin.setContext(this.ctx);
|
||||
plugin.setView(this.app);
|
||||
plugin.onResume(true);
|
||||
return plugin;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Error adding plugin "+className+".");
|
||||
}
|
||||
return null;
|
||||
public PluginManager(WebView app, CordovaInterface ctx) {
|
||||
super(app, ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the loaded plugin.
|
||||
*
|
||||
* If the plugin is not already loaded then load it.
|
||||
*
|
||||
* @param className The class of the loaded plugin.
|
||||
* @return
|
||||
*/
|
||||
private IPlugin getPlugin(String pluginName) {
|
||||
String className = this.services.get(pluginName);
|
||||
if (this.plugins.containsKey(className)) {
|
||||
return this.plugins.get(className);
|
||||
} else {
|
||||
return this.addPlugin(pluginName, className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a class that implements a service.
|
||||
* This does not create the class instance. It just maps service name to class name.
|
||||
*
|
||||
* @param serviceType
|
||||
* @param className
|
||||
*/
|
||||
public void addService(String serviceType, String className) {
|
||||
this.services.put(serviceType, className);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
java.util.Set<Entry<String,IPlugin>> s = this.plugins.entrySet();
|
||||
java.util.Iterator<Entry<String,IPlugin>> it = s.iterator();
|
||||
while(it.hasNext()) {
|
||||
Entry<String,IPlugin> entry = it.next();
|
||||
IPlugin plugin = entry.getValue();
|
||||
plugin.onPause(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) {
|
||||
java.util.Set<Entry<String,IPlugin>> s = this.plugins.entrySet();
|
||||
java.util.Iterator<Entry<String,IPlugin>> it = s.iterator();
|
||||
while(it.hasNext()) {
|
||||
Entry<String,IPlugin> entry = it.next();
|
||||
IPlugin plugin = entry.getValue();
|
||||
plugin.onResume(multitasking);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The final call you receive before your activity is destroyed.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
java.util.Set<Entry<String,IPlugin>> s = this.plugins.entrySet();
|
||||
java.util.Iterator<Entry<String,IPlugin>> it = s.iterator();
|
||||
while(it.hasNext()) {
|
||||
Entry<String,IPlugin> entry = it.next();
|
||||
IPlugin plugin = entry.getValue();
|
||||
plugin.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity receives a new intent.
|
||||
*/
|
||||
public void onNewIntent(Intent intent) {
|
||||
java.util.Set<Entry<String,IPlugin>> s = this.plugins.entrySet();
|
||||
java.util.Iterator<Entry<String,IPlugin>> it = s.iterator();
|
||||
while(it.hasNext()) {
|
||||
Entry<String,IPlugin> entry = it.next();
|
||||
IPlugin plugin = entry.getValue();
|
||||
plugin.onNewIntent(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the URL of the webview changes.
|
||||
*
|
||||
* @param url The URL that is being changed to.
|
||||
* @return Return false to allow the URL to load, return true to prevent the URL from loading.
|
||||
*/
|
||||
public boolean onOverrideUrlLoading(String url) {
|
||||
Iterator<Entry<String, String>> it = this.urlMap.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
HashMap.Entry<String, String> pairs = it.next();
|
||||
if (url.startsWith(pairs.getKey())) {
|
||||
return this.getPlugin(pairs.getValue()).onOverrideUrlLoading(url);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void pluginConfigurationMissing() {
|
||||
System.err.println("=====================================================================================");
|
||||
System.err.println("ERROR: plugin.xml is missing. Add res/xml/plugins.xml to your project.");
|
||||
System.err.println("https://raw.github.com/phonegap/phonegap-android/master/framework/res/xml/plugins.xml");
|
||||
System.err.println("=====================================================================================");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,129 +1,53 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
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;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class PluginResult {
|
||||
private final int status;
|
||||
private final String message;
|
||||
private boolean keepCallback = false;
|
||||
private String cast = null;
|
||||
public class PluginResult extends org.apache.cordova.api.PluginResult {
|
||||
|
||||
public PluginResult(Status status) {
|
||||
this.status = status.ordinal();
|
||||
this.message = "'" + PluginResult.StatusMessages[this.status] + "'";
|
||||
super(status);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, String message) {
|
||||
this.status = status.ordinal();
|
||||
this.message = JSONObject.quote(message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONArray message, String cast) {
|
||||
this.status = status.ordinal();
|
||||
this.message = message.toString();
|
||||
this.cast = cast;
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONObject message, String cast) {
|
||||
this.status = status.ordinal();
|
||||
this.message = message.toString();
|
||||
this.cast = cast;
|
||||
super(status, message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONArray message) {
|
||||
this.status = status.ordinal();
|
||||
this.message = message.toString();
|
||||
super(status, message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONObject message) {
|
||||
this.status = status.ordinal();
|
||||
this.message = message.toString();
|
||||
super(status, message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, int i) {
|
||||
this.status = status.ordinal();
|
||||
this.message = ""+i;
|
||||
super(status, i);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, float f) {
|
||||
this.status = status.ordinal();
|
||||
this.message = ""+f;
|
||||
super(status, f);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, boolean b) {
|
||||
this.status = status.ordinal();
|
||||
this.message = ""+b;
|
||||
}
|
||||
|
||||
public void setKeepCallback(boolean b) {
|
||||
this.keepCallback = b;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public boolean getKeepCallback() {
|
||||
return this.keepCallback;
|
||||
}
|
||||
|
||||
public String getJSONString() {
|
||||
return "{status:" + this.status + ",message:" + this.message + ",keepCallback:" + this.keepCallback + "}";
|
||||
}
|
||||
|
||||
public String toSuccessCallbackString(String callbackId) {
|
||||
StringBuffer buf = new StringBuffer("");
|
||||
if (cast != null) {
|
||||
buf.append("var temp = "+cast+"("+this.getJSONString() + ");\n");
|
||||
buf.append("PhoneGap.callbackSuccess('"+callbackId+"',temp);");
|
||||
}
|
||||
else {
|
||||
buf.append("PhoneGap.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String toErrorCallbackString(String callbackId) {
|
||||
return "PhoneGap.callbackError('"+callbackId+"', " + this.getJSONString()+ ");";
|
||||
}
|
||||
|
||||
public static String[] StatusMessages = new String[] {
|
||||
"No result",
|
||||
"OK",
|
||||
"Class not found",
|
||||
"Illegal access",
|
||||
"Instantiation error",
|
||||
"Malformed url",
|
||||
"IO error",
|
||||
"Invalid action",
|
||||
"JSON error",
|
||||
"Error"
|
||||
};
|
||||
|
||||
public enum Status {
|
||||
NO_RESULT,
|
||||
OK,
|
||||
CLASS_NOT_FOUND_EXCEPTION,
|
||||
ILLEGAL_ACCESS_EXCEPTION,
|
||||
INSTANTIATION_EXCEPTION,
|
||||
MALFORMED_URL_EXCEPTION,
|
||||
IO_EXCEPTION,
|
||||
INVALID_ACTION,
|
||||
JSON_EXCEPTION,
|
||||
ERROR
|
||||
super(status, b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.phonegap.file;
|
||||
|
||||
public class EncodingException extends Exception {
|
||||
|
||||
public EncodingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.phonegap.file;
|
||||
|
||||
public class FileExistsException extends Exception {
|
||||
|
||||
public FileExistsException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.phonegap.file;
|
||||
|
||||
public class InvalidModificationException extends Exception {
|
||||
|
||||
public InvalidModificationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.phonegap.file;
|
||||
|
||||
public class NoModificationAllowedException extends Exception {
|
||||
|
||||
public NoModificationAllowedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.phonegap.file;
|
||||
|
||||
public class TypeMismatchException extends Exception {
|
||||
|
||||
public TypeMismatchException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,32 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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 com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
@@ -61,7 +72,7 @@ public class AccelListener extends Plugin implements SensorEventListener {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
public void setContext(CordovaInterface ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
@@ -137,7 +148,10 @@ public class AccelListener extends Plugin implements SensorEventListener {
|
||||
else if (action.equals("getTimeout")) {
|
||||
float f = this.getTimeout();
|
||||
return new PluginResult(status, f);
|
||||
}
|
||||
} else {
|
||||
// Unsupported action
|
||||
return new PluginResult(PluginResult.Status.INVALID_ACTION);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
@@ -156,7 +170,7 @@ public class AccelListener extends Plugin implements SensorEventListener {
|
||||
}
|
||||
else if (action.equals("getAcceleration")) {
|
||||
// Can only return value if RUNNING
|
||||
if (this.status == RUNNING) {
|
||||
if (this.status == AccelListener.RUNNING) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,30 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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 com.phonegap.api.LOG;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
@@ -58,9 +70,6 @@ public class App extends Plugin {
|
||||
else if (action.equals("exitApp")) {
|
||||
this.exitApp();
|
||||
}
|
||||
else if (action.equals("addWhiteListEntry")) {
|
||||
this.addWhiteListEntry(args.getString(0), args.optBoolean(1));
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
@@ -186,14 +195,4 @@ public class App extends Plugin {
|
||||
public void exitApp() {
|
||||
((DroidGap)this.ctx).endActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
((DroidGap)this.ctx).addWhiteListEntry(origin, subdomains);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,30 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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 com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import java.util.ArrayList;
|
||||
|
||||
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;
|
||||
|
||||
@@ -18,7 +32,7 @@ import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* This class called by PhonegapActivity to play and record audio.
|
||||
* 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):
|
||||
@@ -30,13 +44,16 @@ import java.util.Map.Entry;
|
||||
*/
|
||||
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>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,15 +131,45 @@ public class AudioHandler extends Plugin {
|
||||
* Stop all audio players and recorders.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
java.util.Set<Entry<String,AudioPlayer>> s = this.players.entrySet();
|
||||
java.util.Iterator<Entry<String,AudioPlayer>> it = s.iterator();
|
||||
while(it.hasNext()) {
|
||||
Entry<String,AudioPlayer> entry = it.next();
|
||||
AudioPlayer audio = entry.getValue();
|
||||
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
|
||||
*/
|
||||
public void 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
@@ -1,11 +1,22 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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;
|
||||
@@ -20,8 +31,8 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This class implements the audio playback and recording capabilities used by PhoneGap.
|
||||
* It is called by the AudioHandler PhoneGap class.
|
||||
* 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:
|
||||
@@ -33,11 +44,11 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
private static final String LOG_TAG = "AudioPlayer";
|
||||
|
||||
// AudioPlayer states
|
||||
private static int MEDIA_NONE = 0;
|
||||
private static int MEDIA_STARTING = 1;
|
||||
private static int MEDIA_RUNNING = 2;
|
||||
private static int MEDIA_PAUSED = 3;
|
||||
private static int MEDIA_STOPPED = 4;
|
||||
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;
|
||||
@@ -105,7 +116,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
public void startRecording(String file) {
|
||||
if (this.mPlayer != null) {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
}
|
||||
|
||||
// Make sure we're not already recording
|
||||
@@ -126,11 +137,11 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +183,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
public void startPlaying(String file) {
|
||||
if (this.recorder != null) {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode.");
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
}
|
||||
|
||||
// If this is a new request to play audio, or stopped
|
||||
@@ -217,7 +228,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +242,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: "+this.state);
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_ABORTED+");");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +254,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
if (this.mPlayer != null) {
|
||||
this.mPlayer.seekTo(milliseconds);
|
||||
Log.d(LOG_TAG, "Send a onStatus update for the new seek");
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_POSITION+", "+milliseconds/1000.0f+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_POSITION+", "+milliseconds/1000.0f+");");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +270,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: "+this.state);
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_NONE_ACTIVE+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_NONE_ACTIVE+");");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +284,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
}
|
||||
else {
|
||||
Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: "+this.state);
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_NONE_ACTIVE+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+MEDIA_ERR_NONE_ACTIVE+");");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +305,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
public long getCurrentPosition() {
|
||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
||||
int curPos = this.mPlayer.getCurrentPosition();
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_POSITION+", "+curPos/1000.0f+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_POSITION+", "+curPos/1000.0f+");");
|
||||
return curPos;
|
||||
}
|
||||
else {
|
||||
@@ -373,7 +384,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
this.prepareOnly = false;
|
||||
|
||||
// Send status notification to JavaScript
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_DURATION+","+this.duration+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_DURATION+","+this.duration+");");
|
||||
|
||||
}
|
||||
|
||||
@@ -402,7 +413,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
this.mPlayer.release();
|
||||
|
||||
// Send error notification to JavaScript
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_ERROR+", "+arg1+");");
|
||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", "+arg1+");");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -413,11 +424,20 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
||||
*/
|
||||
private void setState(int state) {
|
||||
if (this.state != state) {
|
||||
this.handler.sendJavascript("PhoneGap.Media.onStatus('" + this.id + "', "+MEDIA_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
|
||||
69
framework/src/org/apache/cordova/AuthenticationToken.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
/**
|
||||
* The Class AuthenticationToken defines the userName and password to be used for authenticating a web resource
|
||||
*/
|
||||
public class AuthenticationToken {
|
||||
private String userName;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Gets the user name.
|
||||
*
|
||||
* @return the user name
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user name.
|
||||
*
|
||||
* @param userName
|
||||
* the new user name
|
||||
*/
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the password.
|
||||
*
|
||||
* @return the password
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
*
|
||||
* @param password
|
||||
* the new password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,18 +1,29 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010-2011, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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 com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -1,11 +1,22 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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;
|
||||
@@ -20,7 +31,7 @@ import java.util.LinkedList;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class provides a way for Java to run JavaScript in the web page that has loaded PhoneGap.
|
||||
* 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.
|
||||
*
|
||||
@@ -96,10 +107,10 @@ public class CallbackServer implements Runnable {
|
||||
/**
|
||||
* Init callback server and start XHR if running local app.
|
||||
*
|
||||
* If PhoneGap app is loaded from file://, then we can use XHR
|
||||
* 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 PhoneGap app being loaded
|
||||
* @param url The URL of the Cordova app being loaded
|
||||
*/
|
||||
public void init(String url) {
|
||||
//System.out.println("CallbackServer.start("+url+")");
|
||||
@@ -126,7 +137,7 @@ public class CallbackServer implements Runnable {
|
||||
/**
|
||||
* Re-init when loading a new HTML page into webview.
|
||||
*
|
||||
* @param url The URL of the PhoneGap app being loaded
|
||||
* @param url The URL of the Cordova app being loaded
|
||||
*/
|
||||
public void reinit(String url) {
|
||||
this.stopServer();
|
||||
@@ -303,9 +314,10 @@ public class CallbackServer implements Runnable {
|
||||
* @return int
|
||||
*/
|
||||
public int getSize() {
|
||||
int size = this.javascript.size();
|
||||
//System.out.println("getSize() = " + size);
|
||||
return size;
|
||||
synchronized(this) {
|
||||
int size = this.javascript.size();
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,17 +326,16 @@ public class CallbackServer implements Runnable {
|
||||
* @return String
|
||||
*/
|
||||
public String getJavascript() {
|
||||
if (this.javascript.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
String statement = this.javascript.remove(0);
|
||||
//System.out.println("CallbackServer.getJavascript() = " + statement);
|
||||
if (this.javascript.size() == 0) {
|
||||
synchronized (this) {
|
||||
this.empty = true;
|
||||
}
|
||||
}
|
||||
return statement;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,12 +344,11 @@ public class CallbackServer implements Runnable {
|
||||
* @param statement
|
||||
*/
|
||||
public void sendJavascript(String statement) {
|
||||
//System.out.println("CallbackServer.sendJavascript("+statement+")");
|
||||
this.javascript.add(statement);
|
||||
synchronized (this) {
|
||||
this.empty = false;
|
||||
this.notify();
|
||||
}
|
||||
synchronized (this) {
|
||||
this.javascript.add(statement);
|
||||
this.empty = false;
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/* The Following code has been modified from original implementation of URLEncoder */
|
||||
@@ -1,11 +1,22 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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;
|
||||
@@ -15,19 +26,20 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
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 com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import com.phonegap.api.LOG;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
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;
|
||||
@@ -90,23 +102,19 @@ public class CameraLauncher extends Plugin {
|
||||
try {
|
||||
if (action.equals("takePicture")) {
|
||||
int srcType = CAMERA;
|
||||
int destType = DATA_URL;
|
||||
int destType = FILE_URI;
|
||||
this.targetHeight = 0;
|
||||
this.targetWidth = 0;
|
||||
this.encodingType = JPEG;
|
||||
this.mediaType = PICTURE;
|
||||
this.mQuality = 80;
|
||||
|
||||
JSONObject options = args.optJSONObject(0);
|
||||
if (options != null) {
|
||||
srcType = options.getInt("sourceType");
|
||||
destType = options.getInt("destinationType");
|
||||
this.targetHeight = options.getInt("targetHeight");
|
||||
this.targetWidth = options.getInt("targetWidth");
|
||||
this.encodingType = options.getInt("encodingType");
|
||||
this.mediaType = options.getInt("mediaType");
|
||||
this.mQuality = options.getInt("quality");
|
||||
}
|
||||
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);
|
||||
|
||||
if (srcType == CAMERA) {
|
||||
this.takePicture(destType, encodingType);
|
||||
@@ -132,7 +140,7 @@ public class CameraLauncher extends Plugin {
|
||||
/**
|
||||
* Take a picture with the camera.
|
||||
* When an image is captured or the camera view is cancelled, the result is returned
|
||||
* in PhonegapActivity.onActivityResult, which forwards the result to this.onActivityResult.
|
||||
* 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:
|
||||
@@ -168,9 +176,11 @@ public class CameraLauncher extends Plugin {
|
||||
private File createCaptureFile(int encodingType) {
|
||||
File photo = null;
|
||||
if (encodingType == JPEG) {
|
||||
photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Pic.jpg");
|
||||
photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Pic.jpg");
|
||||
} else if (encodingType == PNG) {
|
||||
photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Pic.png");
|
||||
} else {
|
||||
photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Pic.png");
|
||||
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
|
||||
}
|
||||
return photo;
|
||||
}
|
||||
@@ -263,19 +273,24 @@ public class CameraLauncher extends Plugin {
|
||||
// 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(ctx.getContext()) + "/Pic.jpg");
|
||||
exif.readExifData();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// If CAMERA
|
||||
if (srcType == CAMERA) {
|
||||
// If image available
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
try {
|
||||
// Create an ExifHelper to save the exif data that is lost during compression
|
||||
ExifHelper exif = new ExifHelper();
|
||||
if (this.encodingType == JPEG) {
|
||||
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx) + "/Pic.jpg");
|
||||
exif.readExifData();
|
||||
}
|
||||
|
||||
// Read in bitmap of captured image
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
@@ -366,6 +381,20 @@ public class CameraLauncher extends Plugin {
|
||||
if (destType == DATA_URL) {
|
||||
try {
|
||||
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
|
||||
String[] cols = { MediaStore.Images.Media.ORIENTATION };
|
||||
Cursor cursor = this.ctx.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();
|
||||
@@ -385,15 +414,23 @@ public class CameraLauncher extends Plugin {
|
||||
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
|
||||
bitmap = scaleBitmap(bitmap);
|
||||
|
||||
String fileName = DirectoryManager.getTempDirectoryPath(ctx) + "/resize.jpg";
|
||||
String fileName = DirectoryManager.getTempDirectoryPath(ctx.getContext()) + "/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;
|
||||
|
||||
this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName)), this.callbackId);
|
||||
// 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();
|
||||
@@ -486,4 +523,4 @@ public class CameraLauncher extends Plugin {
|
||||
public void failPicture(String err) {
|
||||
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,30 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2011, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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;
|
||||
@@ -24,13 +38,11 @@ import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.phonegap.api.LOG;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
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";
|
||||
|
||||
@@ -38,6 +50,13 @@ public class Capture extends Plugin {
|
||||
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
|
||||
@@ -110,7 +129,7 @@ public class Capture extends Plugin {
|
||||
else if (mimeType.endsWith(AUDIO_3GPP)) {
|
||||
obj = getAudioVideoData(filePath, obj, false);
|
||||
}
|
||||
else if (mimeType.equals(VIDEO_3GPP)) {
|
||||
else if (mimeType.equals(VIDEO_3GPP) || mimeType.equals(VIDEO_MP4)) {
|
||||
obj = getAudioVideoData(filePath, obj, true);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +168,7 @@ public class Capture extends Plugin {
|
||||
try {
|
||||
player.setDataSource(filePath);
|
||||
player.prepare();
|
||||
obj.put("duration", player.getDuration());
|
||||
obj.put("duration", player.getDuration()/1000);
|
||||
if (video) {
|
||||
obj.put("height", player.getVideoHeight());
|
||||
obj.put("width", player.getVideoWidth());
|
||||
@@ -177,7 +196,7 @@ public class Capture extends Plugin {
|
||||
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(ctx), "Capture.jpg");
|
||||
File photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Capture.jpg");
|
||||
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
|
||||
this.imageUri = Uri.fromFile(photo);
|
||||
|
||||
@@ -217,7 +236,7 @@ public class Capture extends Plugin {
|
||||
|
||||
if (results.length() >= limit) {
|
||||
// Send Uri back to JavaScript for listening to audio
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results, "navigator.device.capture._castMediaFile"), this.callbackId);
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
} else {
|
||||
// still need to capture more audio clips
|
||||
captureAudio();
|
||||
@@ -230,7 +249,7 @@ public class Capture extends Plugin {
|
||||
try {
|
||||
// Create an ExifHelper to save the exif data that is lost during compression
|
||||
ExifHelper exif = new ExifHelper();
|
||||
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx) + "/Capture.jpg");
|
||||
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx.getContext()) + "/Capture.jpg");
|
||||
exif.readExifData();
|
||||
|
||||
// Read in bitmap of captured image
|
||||
@@ -249,7 +268,7 @@ public class Capture extends Plugin {
|
||||
uri = this.ctx.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("Error capturing image - no media storage found.");
|
||||
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -272,14 +291,14 @@ public class Capture extends Plugin {
|
||||
|
||||
if (results.length() >= limit) {
|
||||
// Send Uri back to JavaScript for viewing image
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results, "navigator.device.capture._castMediaFile"), this.callbackId);
|
||||
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("Error capturing image.");
|
||||
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image."));
|
||||
}
|
||||
} else if (requestCode == CAPTURE_VIDEO) {
|
||||
// Get the uri of the video clip
|
||||
@@ -289,7 +308,7 @@ public class Capture extends Plugin {
|
||||
|
||||
if (results.length() >= limit) {
|
||||
// Send Uri back to JavaScript for viewing video
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results, "navigator.device.capture._castMediaFile"), this.callbackId);
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
} else {
|
||||
// still need to capture more video clips
|
||||
captureVideo(duration);
|
||||
@@ -300,22 +319,22 @@ public class Capture extends Plugin {
|
||||
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, "navigator.device.capture._castMediaFile"), this.callbackId);
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
}
|
||||
// user canceled the action
|
||||
else {
|
||||
this.fail("Canceled.");
|
||||
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, "navigator.device.capture._castMediaFile"), this.callbackId);
|
||||
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
|
||||
}
|
||||
// something bad happened
|
||||
else {
|
||||
this.fail("Did not complete!");
|
||||
this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Did not complete!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,13 +377,24 @@ public class Capture extends Plugin {
|
||||
|
||||
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(String err) {
|
||||
public void fail(JSONObject err) {
|
||||
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,32 @@
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
package com.phonegap;
|
||||
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 com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
@@ -48,6 +59,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
* Constructor.
|
||||
*/
|
||||
public CompassListener() {
|
||||
this.heading = 0;
|
||||
this.timeStamp = 0;
|
||||
this.setStatus(CompassListener.STOPPED);
|
||||
}
|
||||
@@ -58,7 +70,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
public void setContext(CordovaInterface ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
@@ -88,10 +100,10 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
}
|
||||
else if (action.equals("getHeading")) {
|
||||
// If not running, then this is an async call, so don't worry about waiting
|
||||
if (this.status != RUNNING) {
|
||||
if (this.status != CompassListener.RUNNING) {
|
||||
int r = this.start();
|
||||
if (r == ERROR_FAILED_TO_START) {
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, ERROR_FAILED_TO_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;
|
||||
@@ -104,11 +116,10 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
}
|
||||
}
|
||||
if (timeout == 0) {
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
|
||||
return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START);
|
||||
}
|
||||
}
|
||||
//float f = this.getHeading();
|
||||
return new PluginResult(status, getCompassHeading(), "navigator.compass._castDate");
|
||||
return new PluginResult(status, getCompassHeading());
|
||||
}
|
||||
else if (action.equals("setTimeout")) {
|
||||
this.setTimeout(args.getLong(0));
|
||||
@@ -116,6 +127,9 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
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) {
|
||||
@@ -136,7 +150,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
}
|
||||
else if (action.equals("getHeading")) {
|
||||
// Can only return value if RUNNING
|
||||
if (this.status == RUNNING) {
|
||||
if (this.status == CompassListener.RUNNING) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -169,11 +183,11 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
// Get accelerometer from sensor manager
|
||||
// Get compass sensor from sensor manager
|
||||
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
|
||||
|
||||
// If found, then register as listener
|
||||
if (list.size() > 0) {
|
||||
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();
|
||||
@@ -1,11 +1,3 @@
|
||||
// Taken from Android Tutorials
|
||||
/*
|
||||
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
|
||||
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
|
||||
*
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
@@ -22,11 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.phonegap;
|
||||
package org.apache.cordova;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
@@ -42,11 +35,11 @@ import org.json.JSONObject;
|
||||
* Eclair or higher, we want to use {@link ContactAccessorSdk5}.
|
||||
*/
|
||||
public abstract class ContactAccessor {
|
||||
|
||||
|
||||
protected final String LOG_TAG = "ContactsAccessor";
|
||||
protected Activity mApp;
|
||||
protected Context mApp;
|
||||
protected WebView mView;
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if the data associated with the key is required to
|
||||
* be populated in the Contact object.
|
||||
@@ -55,21 +48,21 @@ public abstract class ContactAccessor {
|
||||
* @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();
|
||||
}
|
||||
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("*")) {
|
||||
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);
|
||||
@@ -83,89 +76,89 @@ public abstract class ContactAccessor {
|
||||
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("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 {
|
||||
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("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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
public abstract String save(JSONObject contact);
|
||||
|
||||
/**
|
||||
* Handles searching through SDK-specific contacts API.
|
||||
@@ -181,25 +174,25 @@ public abstract class ContactAccessor {
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
1936
framework/src/org/apache/cordova/ContactAccessorSdk5.java
Normal file
101
framework/src/org/apache/cordova/ContactManager.java
Executable 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 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.getContext());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
314
framework/src/org/apache/cordova/CordovaChromeClient.java
Executable file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
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.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
|
||||
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 DroidGap ctx;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
public CordovaChromeClient(Context ctx) {
|
||||
this.ctx = (DroidGap) ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
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);
|
||||
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.ctx.baseUrl) == 0 || ctx.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 = ctx.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 = ctx.callbackServer.getJavascript();
|
||||
result.confirm(r);
|
||||
}
|
||||
|
||||
// Calling into CallbackServer
|
||||
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
|
||||
String r = "";
|
||||
if (message.equals("usePolling")) {
|
||||
r = ""+ ctx.callbackServer.usePolling();
|
||||
}
|
||||
else if (message.equals("restartServer")) {
|
||||
ctx.callbackServer.restartServer();
|
||||
}
|
||||
else if (message.equals("getPort")) {
|
||||
r = Integer.toString(ctx.callbackServer.getPort());
|
||||
}
|
||||
else if (message.equals("getToken")) {
|
||||
r = ctx.callbackServer.getToken();
|
||||
}
|
||||
result.confirm(r);
|
||||
}
|
||||
|
||||
// Cordova JS has initialized, so show webview
|
||||
// (This solves white flash seen when rendering HTML)
|
||||
else if (reqOk && defaultValue != null && defaultValue.equals("gap_init:")) {
|
||||
ctx.appView.setVisibility(View.VISIBLE);
|
||||
ctx.spinnerStop();
|
||||
result.confirm("OK");
|
||||
}
|
||||
|
||||
// Show dialog
|
||||
else {
|
||||
final JsPromptResult res = result;
|
||||
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx);
|
||||
dlg.setMessage(message);
|
||||
final EditText input = new EditText(this.ctx);
|
||||
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
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
307
framework/src/org/apache/cordova/CordovaWebViewClient.java
Executable file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
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 android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.net.http.SslError;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.HttpAuthHandler;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
/**
|
||||
* This class is the WebViewClient that implements callbacks for our web view.
|
||||
*/
|
||||
public class CordovaWebViewClient extends WebViewClient {
|
||||
|
||||
private static final String TAG = "Cordova";
|
||||
DroidGap ctx;
|
||||
private boolean doClearHistory = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
public CordovaWebViewClient(DroidGap ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the host application a chance to take over the control when a new url
|
||||
* is about to be loaded in the current WebView.
|
||||
*
|
||||
* @param view The WebView that is initiating the callback.
|
||||
* @param url The url to be loaded.
|
||||
* @return true to override, false for default behavior
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
|
||||
// First give any plugins the chance to handle the url themselves
|
||||
if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) {
|
||||
}
|
||||
|
||||
// If dialing phone (tel:5551212)
|
||||
else if (url.startsWith(WebView.SCHEME_TEL)) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_DIAL);
|
||||
intent.setData(Uri.parse(url));
|
||||
ctx.startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error dialing "+url+": "+ e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// If displaying map (geo:0,0?q=address)
|
||||
else if (url.startsWith("geo:")) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
ctx.startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error showing map "+url+": "+ e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// If sending email (mailto:abc@corp.com)
|
||||
else if (url.startsWith(WebView.SCHEME_MAILTO)) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
ctx.startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error sending email "+url+": "+ e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// If sms:5551212?body=This is the message
|
||||
else if (url.startsWith("sms:")) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
|
||||
// Get address
|
||||
String address = null;
|
||||
int parmIndex = url.indexOf('?');
|
||||
if (parmIndex == -1) {
|
||||
address = url.substring(4);
|
||||
}
|
||||
else {
|
||||
address = url.substring(4, parmIndex);
|
||||
|
||||
// If body, then set sms body
|
||||
Uri uri = Uri.parse(url);
|
||||
String query = uri.getQuery();
|
||||
if (query != null) {
|
||||
if (query.startsWith("body=")) {
|
||||
intent.putExtra("sms_body", query.substring(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
intent.setData(Uri.parse("sms:"+address));
|
||||
intent.putExtra("address", address);
|
||||
intent.setType("vnd.android-dir/mms-sms");
|
||||
ctx.startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error sending sms "+url+":"+ e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// All else
|
||||
else {
|
||||
|
||||
// If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
|
||||
// Our app continues to run. When BACK is pressed, our app is redisplayed.
|
||||
if (url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0 || ctx.isUrlWhiteListed(url)) {
|
||||
this.ctx.loadUrl(url);
|
||||
}
|
||||
|
||||
// If not our application, let default viewer handle
|
||||
else {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
ctx.startActivity(intent);
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
LOG.e(TAG, "Error loading url "+url, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* On received http auth request.
|
||||
* The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
|
||||
*
|
||||
* @param view
|
||||
* the view
|
||||
* @param handler
|
||||
* the handler
|
||||
* @param host
|
||||
* the host
|
||||
* @param realm
|
||||
* the realm
|
||||
*/
|
||||
@Override
|
||||
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
|
||||
String realm) {
|
||||
|
||||
// get the authentication token
|
||||
AuthenticationToken token = ctx.getAuthenticationToken(host,realm);
|
||||
|
||||
if(token != null) {
|
||||
handler.proceed(token.getUserName(), token.getPassword());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
// Clear history so history.back() doesn't do anything.
|
||||
// So we can reinit() native side CallbackServer & PluginManager.
|
||||
view.clearHistory();
|
||||
this.doClearHistory = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the host application that a page has finished loading.
|
||||
*
|
||||
* @param view The webview initiating the callback.
|
||||
* @param url The url of the page.
|
||||
*/
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
|
||||
/**
|
||||
* Because of a timing issue we need to clear this history in onPageFinished as well as
|
||||
* onPageStarted. However we only want to do this if the doClearHistory boolean is set to
|
||||
* true. You see when you load a url with a # in it which is common in jQuery applications
|
||||
* onPageStared is not called. Clearing the history at that point would break jQuery apps.
|
||||
*/
|
||||
if (this.doClearHistory) {
|
||||
view.clearHistory();
|
||||
this.doClearHistory = false;
|
||||
}
|
||||
|
||||
// Clear timeout flag
|
||||
this.ctx.loadUrlTimeout++;
|
||||
|
||||
// Try firing the onNativeReady event in JS. If it fails because the JS is
|
||||
// not loaded yet then just set a flag so that the onNativeReady can be fired
|
||||
// from the JS side when the JS gets to that code.
|
||||
if (!url.equals("about:blank")) {
|
||||
ctx.appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}");
|
||||
this.ctx.postMessage("onNativeReady", null);
|
||||
}
|
||||
|
||||
// Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
|
||||
if (ctx.appView.getVisibility() == View.INVISIBLE) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
ctx.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
ctx.appView.setVisibility(View.VISIBLE);
|
||||
ctx.spinnerStop();
|
||||
}
|
||||
});
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
|
||||
// Shutdown if blank loaded
|
||||
if (url.equals("about:blank")) {
|
||||
if (this.ctx.callbackServer != null) {
|
||||
this.ctx.callbackServer.destroy();
|
||||
}
|
||||
this.ctx.endActivity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 view The WebView that is initiating the callback.
|
||||
* @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.
|
||||
*/
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
LOG.d(TAG, "DroidGap: GapViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
|
||||
|
||||
// Clear timeout flag
|
||||
this.ctx.loadUrlTimeout++;
|
||||
|
||||
// Stop "app loading" spinner if showing
|
||||
this.ctx.spinnerStop();
|
||||
|
||||
// Handle error
|
||||
this.ctx.onReceivedError(errorCode, description, failingUrl);
|
||||
}
|
||||
|
||||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
|
||||
|
||||
final String packageName = this.ctx.getPackageName();
|
||||
final PackageManager pm = this.ctx.getPackageManager();
|
||||
ApplicationInfo appInfo;
|
||||
try {
|
||||
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
|
||||
if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
|
||||
// debug = true
|
||||
handler.proceed();
|
||||
return;
|
||||
} else {
|
||||
// debug = false
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// When it doubt, lock it out!
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
|
||||
/*
|
||||
* If you do a document.location.href the url does not get pushed on the stack
|
||||
* so we do a check here to see if the url should be pushed.
|
||||
*/
|
||||
if (!this.ctx.peekAtUrlStack().equals(url)) {
|
||||
this.ctx.pushUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
219
framework/src/org/apache/cordova/Device.java
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
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.TimeZone;
|
||||
|
||||
import org.apache.cordova.api.LOG;
|
||||
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.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
public class Device extends Plugin {
|
||||
public static final String TAG = "Device";
|
||||
|
||||
public static String cordovaVersion = "1.6.0rc1"; // Cordova version
|
||||
public static String platform = "Android"; // Device OS
|
||||
public static String uuid; // Device UUID
|
||||
|
||||
BroadcastReceiver telephonyReceiver = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public Device() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
Device.uuid = getUuid();
|
||||
this.initTelephonyReceiver();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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("getDeviceInfo")) {
|
||||
JSONObject r = new JSONObject();
|
||||
r.put("uuid", Device.uuid);
|
||||
r.put("version", this.getOSVersion());
|
||||
r.put("platform", Device.platform);
|
||||
r.put("name", this.getProductName());
|
||||
r.put("cordova", Device.cordovaVersion);
|
||||
//JSONObject pg = new JSONObject();
|
||||
//pg.put("version", Device.CordovaVersion);
|
||||
//r.put("cordova", pg);
|
||||
return new PluginResult(status, r);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
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("getDeviceInfo")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister receiver.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
this.ctx.unregisterReceiver(this.telephonyReceiver);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Listen for telephony events: RINGING, OFFHOOK and IDLE
|
||||
* Send these events to all plugins using
|
||||
* DroidGap.onMessage("telephone", "ringing" | "offhook" | "idle")
|
||||
*/
|
||||
private void initTelephonyReceiver() {
|
||||
IntentFilter intentFilter = new IntentFilter() ;
|
||||
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
|
||||
final CordovaInterface myctx = this.ctx;
|
||||
this.telephonyReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
// If state has changed
|
||||
if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
|
||||
if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) {
|
||||
String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
|
||||
if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
|
||||
LOG.i(TAG, "Telephone RINGING");
|
||||
myctx.postMessage("telephone", "ringing");
|
||||
}
|
||||
else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
|
||||
LOG.i(TAG, "Telephone OFFHOOK");
|
||||
myctx.postMessage("telephone", "offhook");
|
||||
}
|
||||
else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
|
||||
LOG.i(TAG, "Telephone IDLE");
|
||||
myctx.postMessage("telephone", "idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Register the receiver
|
||||
this.ctx.registerReceiver(this.telephonyReceiver, intentFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OS name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPlatform() {
|
||||
return Device.platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the device's Universally Unique Identifier (UUID).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getUuid() {
|
||||
String uuid = Settings.Secure.getString(this.ctx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Cordova version.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getCordovaVersion() {
|
||||
return Device.cordovaVersion;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
String model = android.os.Build.MODEL;
|
||||
return model;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
String productname = android.os.Build.PRODUCT;
|
||||
return productname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OS version.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getOSVersion() {
|
||||
String osversion = android.os.Build.VERSION.RELEASE;
|
||||
return osversion;
|
||||
}
|
||||
|
||||
public String getSDKVersion() {
|
||||
String sdkversion = android.os.Build.VERSION.SDK;
|
||||
return sdkversion;
|
||||
}
|
||||
|
||||
|
||||
public String getTimeZoneID() {
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
return(tz.getID());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||