Compare commits

...

139 Commits

Author SHA1 Message Date
Joe Bowser
f4da7e164d Incrementing project to 1.7.0rc1 2012-04-23 11:37:33 -07:00
macdonst
05192a91da Removing un-needed logs 2012-04-19 21:03:55 -04:00
Fil Maj
3835144b93 [CB-473] run ant clean before ant debug install 2012-04-19 17:25:19 -07:00
Joe Bowser
bdf452b02a Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-04-19 16:48:32 -07:00
Joe Bowser
bcc2957f20 Fix for CB-549 2012-04-19 16:45:15 -07:00
Fil Maj
81059b398f Proper fix for CB-164. Online/offline events now propagated to webview properly 2012-04-19 16:35:55 -07:00
Fil Maj
31d5a94ea9 [CB-164] Changed network plugin to sync from async and removed setKeepCallback(true) on plugin result in there. Fixes location.reload() not firing deviceready due to network plugin being unresponsive 2012-04-19 12:33:45 -07:00
Joe Bowser
1e5457a47d Reverting the back button change that I made, for some reason certain methods aren't inherited when you extend DroidGap 2012-04-19 12:22:33 -07:00
macdonst
7b75e2f1b0 CB-539: FileTransfer.download fails when target starts with 'file://' 2012-04-18 13:56:29 -04:00
Joe Bowser
180696baec Fixed back button behaviour. WIN 2012-04-17 17:50:07 -07:00
Joe Bowser
76820ebaff CB-480 work, back button and history issues are preventing this from being tested properly 2012-04-17 17:13:33 -07:00
Joe Bowser
c341cf0d47 Adding fix for CB-482 2012-04-17 12:20:23 -07:00
macdonst
f2c38ea0a7 Automatically update index.html in templates directory on version change 2012-04-13 16:36:46 -04:00
Joe Bowser
0772a315c4 CB-489 - Adding .js to the example, thought it was removed for a reason 2012-04-13 13:08:13 -07:00
macdonst
08d7a9c87a Remove duplicate files from repository
We should only have these files in one place in the repo. Changes have been made to the scripts to pick up the xml files from their proper location.
2012-04-13 15:35:49 -04:00
Joe Bowser
eb48055acd Getting setup to tag 1.6.1 2012-04-12 16:37:27 -07:00
Joe Bowser
e4a52de0a5 Copying new XML into the templates for 1.6.1. Turns out tags are broken 2012-04-12 14:33:29 -07:00
macdonst
ac06892dec CB-472: FileWriter.seek(0) does not actually seek to the beginning of the file 2012-04-11 10:44:09 -04:00
Joe Bowser
5e1997c8d8 Updating with tagged JS 2012-04-10 13:26:35 -07:00
Bryce Curtis
36e6b572b7 Update to version 1.6.0. 2012-04-10 09:01:37 -05:00
Joe Bowser
3bda8afdc1 Updating the sample index.html 2012-04-09 17:11:51 -07:00
Joe Bowser
cdf148bb58 Starting Release Process 2012-04-09 17:11:13 -07:00
Joe Bowser
b532cf8545 Fixing the template, since this doesn't have to be unit tested. :) 2012-04-09 13:43:36 -07:00
macdonst
ecebcbabf8 CB-446: Enhance setting data source for local files in AudioPlayer 2012-04-09 10:13:43 -04:00
macdonst
aa00e07b3c Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-04-05 19:52:36 -04:00
macdonst
cb473dfed4 CB-453: FileWriter.append - Chinese characters are not appended to the file correctly 2012-04-05 19:51:45 -04:00
Bryce Curtis
8b05ce41dd Update project template cordova.js reference and title. 2012-04-05 15:39:33 -05:00
macdonst
5d43835db8 CB-446: Enhance setting data source for local files in AudioPlayer 2012-04-05 13:43:00 -04:00
macdonst
838286df96 Return MediaError object and not error code from native side of Media API 2012-04-05 13:31:09 -04:00
macdonst
04aa6d3c38 CB-438: File metadata.modificationTime returns an invalid date 2012-04-04 13:03:39 -04:00
macdonst
e213772f98 Updating cordova.android.js for CB-421 and CB-426 2012-04-03 13:09:31 -04:00
macdonst
0577b4bf5d CB-426: camera.getPicture ignores mediaType in 1.5 2012-04-03 13:02:25 -04:00
Bryce Curtis
a37d0699db [CB-423] Problem displaying patch-9 splash screen. 2012-04-02 11:34:57 -05:00
macdonst
5fa77e97bd CB-163: contactFindOptions.filter does not work as expected on Android 2012-03-30 16:28:04 -04:00
macdonst
8d479c8269 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-03-30 15:31:54 -04:00
macdonst
700ae50e9b CB-321: Media API: 'mediaSuccess' callback param to new Media() is called soon after new obj created 2012-03-30 15:29:26 -04:00
Bryce Curtis
900be3afe0 Tests to verify Android native features. 2012-03-30 11:37:29 -05:00
macdonst
d2b329636f Fixing license header in com.phonegap.api.PluginManager 2012-03-29 15:08:44 -04:00
Fil Maj
993fb296d6 updating network status plugin label and updating cordova-js to latest 2012-03-28 13:47:45 -07:00
macdonst
dfc86b1af1 Fix for CB-389: resolveLocalFileSystemURI does not work on a resized image captured from Camera.getPicture() 2012-03-26 21:35:34 -04:00
macdonst
1e2c38598f CB-383: Fixes issue with misspelled destinationType for Camera.getPicture() 2012-03-24 14:09:57 -04:00
Joe Bowser
9d0e8fa436 Tagged 1.6rc1 2012-03-23 14:30:18 -07:00
Bryce Curtis
9d26598334 [CB-367] Back button event should fire on key up not key down
Also changed menu key and search key to be consistent.
2012-03-23 15:17:09 -05:00
Joe Bowser
a688319ea7 First stab at CB-21, I really need more info before I can close this 2012-03-20 15:22:00 -07:00
Joe Bowser
bbf10e3baa Fixing a bug with File Upload on Android where Chunked mode isn't used by default 2012-03-20 11:25:17 -07:00
Bryce Curtis
7e70d76232 [CB-352] Support initializing DroidGap with existing WebView, WebViewClient and webViewChrome.
[CB-353] Create PluginEntry object to use by PluginManager.
2012-03-19 16:20:57 -05:00
Joe Bowser
04b3e4d847 Fixing CB-343: We need to respect the whitelist 2012-03-16 10:55:06 -07:00
Joe Bowser
dc93556ef0 Checking for the callback server before we call sendJavascript for the Kindle Fire, CB-247 2012-03-15 14:29:25 -07:00
Fil Maj
692a59a692 spacing fixes, null check in getPhoneType in contacts, returning error integers instead of objects in contacts 2012-03-15 12:27:37 -07:00
Joe Bowser
df691518e3 Added temporary Cordova splash for now 2012-03-15 10:54:43 -07:00
Joe Bowser
8f2cdcc049 Changing to the modern icon 2012-03-15 10:48:00 -07:00
Joe Bowser
d27064794c Tweaked File Transfer to fix CB-74 2012-03-13 11:46:25 -07:00
Joe Bowser
8a7af93765 Fixing CB-210 with patch and adding fix for CB-210 2012-03-12 13:30:16 -07:00
Fil Maj
f3c96ce1a0 removed old javascript files and removed unused target + commented out lines in build.xml 2012-03-09 12:36:08 -08:00
Fil Maj
715c0a5bea updates to JS: removing require+define from global scope, tweaking geolocation code, online/offline events fire on document now 2012-03-09 12:32:22 -08:00
Fil Maj
4b05ead3ac cordova.require("cordova") is pretty funny. wish i didnt write it 2012-03-09 11:27:56 -08:00
Fil Maj
b4292868eb switched from "require" syntax to "cordova.require" 2012-03-08 17:58:45 -08:00
Joe Bowser
c5025ee2bb We show the default 404 on non-resolved domains 2012-03-06 14:09:11 -08:00
macdonst
8923e52a5e Adding support for legacy plugins 2012-03-05 15:11:24 -05:00
macdonst
aa4f2cc4d9 Tagging 1.5.0 2012-03-01 21:29:18 -05:00
macdonst
4a23f86411 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-03-01 15:57:31 -05:00
macdonst
a69bd65152 Updating cordova.android.js to override FileReader 2012-03-01 15:57:21 -05:00
Fil Maj
7392b63b99 updating cordova.js to include camera constants fix. added clean dependency to build-javascript target in ant file 2012-03-01 11:56:37 -08:00
macdonst
73aa5cc7c3 Updating cordova.android.js to latest version from Apache git repo 2012-03-01 10:45:27 -05:00
Joe Bowser
7bf35e9c83 Merged cordova.android.js. Please move fixes to the cordova-js project 2012-02-29 17:24:04 -08:00
Joe Bowser
adb871f9e1 Updating the JS, even though it shouldn't be here. CB-290 2012-02-29 17:03:37 -08:00
macdonst
21b7346277 Revert change in location of FileSystem 2012-02-29 13:23:32 -05:00
Joe Bowser
79935d31ef Putting back the CordovaInterface work after talking with Simon 2012-02-29 09:34:46 -08:00
Bryce Curtis
d2fc08959a Fix WebSQL for Android 4.0.2. 2012-02-28 23:26:21 -06:00
Bryce Curtis
3ebc1d71df Updating cordova.android.js with File API fixes. 2012-02-28 22:32:30 -06:00
Bryce Curtis
f6503f8476 File APIs should return error code instead of object. 2012-02-28 22:30:27 -06:00
Fil Maj
d593448182 updating cordova.android.js. This resolves CB-283: unregistration of backbutton event handlers do not fire appropriate native method 2012-02-28 17:21:21 -08:00
Joe Bowser
403b87b68b Reverting interface change, not enough time for testing, need to remove it manually 2012-02-28 16:30:25 -08:00
Joe Bowser
bf69362709 Fix to CordovaInterface methods, DroidGap has the managedQuery since it inherits from Activity. (CB-282) 2012-02-28 11:59:51 -08:00
macdonst
c00fb987f6 Switching to require syntax for AudioPlayer 2012-02-28 13:00:33 -05:00
macdonst
7c6450de50 Fixing the call to Media.onStatus() 2012-02-28 11:02:01 -05:00
macdonst
10cbcd7f5a Adding startActivity method to CordovaInterface as many plugins rely on this method 2012-02-27 13:07:56 -05:00
macdonst
e918ffd751 Tagging 1.5.0rc1 2012-02-25 00:28:06 -05:00
macdonst
3ed41597d2 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android into license 2012-02-24 17:51:20 -05:00
macdonst
5722d976ce Fixing app crash when clicking Menu or Back buttons while splashscreen is being shown. 2012-02-23 12:36:38 -05:00
macdonst
8555c42196 CB-3: Apache source headers in callback-android 2012-02-23 11:36:08 -05:00
macdonst
e85394dd99 Refactoring the checks for file:// into a convenience method 2012-02-22 15:56:03 -05:00
macdonst
cc5cfad58d Removing extraneous logging from DroidGap.java left over from rebase 2012-02-22 10:44:16 -05:00
macdonst
363b1429e3 Fix issue with document.location.href not calling loadUrlIntoView
Now we peek at the history and add the url the stack if loadUrlIntoView is not being called.
2012-02-22 10:19:47 -05:00
macdonst
900ff9ed2c Redirect Issue 2012-02-22 10:18:57 -05:00
Joe Bowser
c9d4276207 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-02-20 12:46:20 -08:00
Bryce Curtis
fef0e429db Update build to use new common cordova.android.js instead of building js from multiple Android js files. 2012-02-20 11:04:37 -08:00
Bryce Curtis
26044ad662 Add cordova.android.js from common-js build. 2012-02-20 11:04:37 -08:00
Fil Maj
42430d5d11 more file:// URI truncation :D 2012-02-20 11:04:37 -08:00
Fil Maj
770a257ed3 trim file:// URI from uri->path conversion method 2012-02-20 11:04:37 -08:00
Fil Maj
9fe1f21c9f Use strings not objects 2012-02-20 11:04:37 -08:00
Fil Maj
49d8d22d7f remove trailing slash 2012-02-20 11:04:37 -08:00
Fil Maj
d274891c2c remove file:// protocol from various fileutils methods 2012-02-20 11:04:36 -08:00
Fil Maj
c099c65365 remove file:// protocol from various fileutils remove methods 2012-02-20 11:04:36 -08:00
Fil Maj
79ba28d6c4 truncating file:// protocol where applicable in metadata func 2012-02-20 11:04:36 -08:00
Fil Maj
b4d1ca6181 Need to add/trim file:// where applicable 2012-02-20 11:04:36 -08:00
Fil Maj
657faaff7f Prefix URIs for file API with file:/// and persistent storage should never point to SD card 2012-02-20 11:04:36 -08:00
Fil Maj
a43e80ae1d Return string for root location in requestFileSystem 2012-02-20 11:04:36 -08:00
Fil Maj
5253b5fb31 removing unnecessary try/catch 2012-02-20 11:04:35 -08:00
Fil Maj
8b12bf79e4 Unifying File API error code/response style 2012-02-20 11:04:35 -08:00
Fil Maj
45d75524c9 Changed JavaScript invoked from PluginResult native code to use new modular JS approach 2012-02-20 11:04:35 -08:00
Fil Maj
8a137395ae changing JS invoked from native to work with modular js 2012-02-20 11:04:35 -08:00
Fil Maj
390fe537f8 woops java type checks! love it! 2012-02-20 11:04:35 -08:00
Fil Maj
40cd71484c Adding unsupported action plugin result return if invalid action string is specified to accel and compass listener plugins 2012-02-20 11:04:35 -08:00
Bryce Curtis
9188773152 Arguments are passed as JSON array, not JSON object. 2012-02-19 00:15:23 -06:00
Bryce Curtis
cc8edea065 Call js code using new common js way. 2012-02-18 13:19:50 -06:00
Bryce Curtis
14b368e731 Update build to use new common cordova.android.js instead of building js from multiple Android js files. 2012-02-17 17:30:25 -06:00
Bryce Curtis
4d03577220 Add cordova.android.js from common-js build. 2012-02-17 17:28:35 -06:00
Joe Bowser
040619cd61 Moved the CordovaInterface over to master, doing this before working on CordovaJS 2012-02-17 13:11:15 -08:00
Fil Maj
d6fef8d6e3 more file:// URI truncation :D 2012-02-17 11:40:22 -08:00
Fil Maj
7c1eb7da9b trim file:// URI from uri->path conversion method 2012-02-17 10:55:04 -08:00
Fil Maj
d87ee719a3 Use strings not objects 2012-02-16 18:17:25 -08:00
Fil Maj
a52ba37cf7 remove trailing slash 2012-02-16 17:48:48 -08:00
Fil Maj
cd667d6af5 remove file:// protocol from various fileutils methods 2012-02-16 17:46:16 -08:00
Fil Maj
7e4158ce94 remove file:// protocol from various fileutils remove methods 2012-02-16 17:31:07 -08:00
Fil Maj
0ba803ff46 truncating file:// protocol where applicable in metadata func 2012-02-16 17:21:03 -08:00
Fil Maj
6c48c6a3a1 Need to add/trim file:// where applicable 2012-02-16 15:33:19 -08:00
Fil Maj
7ee135e516 Prefix URIs for file API with file:/// and persistent storage should never point to SD card 2012-02-16 15:18:13 -08:00
Fil Maj
fd69095d3d Return string for root location in requestFileSystem 2012-02-15 17:30:32 -08:00
Fil Maj
357c0ee1ca removing unnecessary try/catch 2012-02-15 16:57:40 -08:00
Fil Maj
40637c1486 Unifying File API error code/response style 2012-02-15 16:47:32 -08:00
Fil Maj
a84d2eab02 Changed JavaScript invoked from PluginResult native code to use new modular JS approach 2012-02-15 10:39:20 -08:00
Fil Maj
52213541a3 changing JS invoked from native to work with modular js 2012-02-15 10:37:24 -08:00
Fil Maj
c7d4d83476 woops java type checks! love it! 2012-02-15 10:35:20 -08:00
Fil Maj
003e3d4d85 Adding unsupported action plugin result return if invalid action string is specified to accel and compass listener plugins 2012-02-15 10:35:19 -08:00
Joe Bowser
95b9cd0229 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-02-09 15:05:30 -08:00
Joe Bowser
044a61d881 Adding custom headers to upload 2012-02-09 15:02:13 -08:00
macdonst
9aa1cd756a Refactor out the Java casting code
When we return JSON to the Java side it does not have the proper methods such as Contact.save() so we need to cast the JSON to the correct JS object. This used to be done from the Java layer calling the right method to cast the JSON. In this new approach the JavaScript layer will no what needs to be cast and call it's own internal function to do the cast.
2012-02-09 16:41:26 -05:00
Joe Bowser
ee4c91539a Change related to FileTransfer, need to get a test going for this somehow 2012-02-08 16:49:17 -08:00
Joe Bowser
77547f8826 Changing to CordovaInterface in preparation of CordovaWebView 2012-02-06 14:13:34 -08:00
Bryce Curtis
52a3a919f9 Missing first line of license in header. 2012-02-06 10:40:48 -06:00
macdonst
1293d64589 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-02-06 10:16:16 -05:00
Anis Kadri
54968b755b CB-75 contact.remove does not remove the contact fully 2012-02-06 10:13:57 -05:00
macdonst
d8d7c29afe Adding com.phonegap.api stubs for legacy user created plugins 2012-02-06 10:04:02 -05:00
Anis Kadri
1c7626aba2 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-02-03 19:36:27 -08:00
Anis Kadri
e0fea2c352 CB-75 contact.remove does not remove the contact fully 2012-02-03 19:32:31 -08:00
macdonst
210cc2bd5e Fixing MediaFileData problem for MP4 video types
Problem:

Using Capture Video and mediaFile.getFormatData() on Android:

Droid / 2.2.3: successfully get height, width, duration

Samsung Galaxy Tab 10.1 / 3.1: recording appears to succeed,
however height / width / duration all come back as 0.

Fix:

The Samsung Galaxy Tab 10.1 returns a MP4 video and not 3GPP as was expected in the Capture class.
2012-02-03 12:24:45 -05:00
macdonst
664a061d10 Rename to Cordova 2012-02-03 10:38:40 -05:00
Joe Bowser
fa4d6d369a Switching headers. Got OK months ago from Simon and Bryce on re-write. No Android Demo code in current project 2012-02-01 13:09:58 -08:00
179 changed files with 15334 additions and 7265 deletions

8
.gitignore vendored
View File

@@ -1,14 +1,16 @@
.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/com/phonegap/*.class
framework/test/org/apache/cordova/*.class
framework/assets/www/.DS_Store
framework/assets/www/cordova-*.js
framework/assets/www/phonegap-*.js
example
./test

226
LICENSE
View File

@@ -199,228 +199,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SUBCOMPONENTS
Apache Callback includes software components under different license terms.
Your use of these subcomponents is subject to the terms and conditions of
the following licenses.
For the framework/libs/junit-4.10.jar component:
Common Public License - v 1.0
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
1. DEFINITIONS
"Contribution" means:
a) in the case of the initial Contributor, the initial code and
documentation distributed under this Agreement, and
b) in the case of each subsequent Contributor:
i) changes to the Program, and
ii) additions to the Program;
where such changes and/or additions to the Program originate from and are
distributed by that particular Contributor. A Contribution 'originates' from a
Contributor if it was added to the Program by such Contributor itself or anyone
acting on such Contributor's behalf. Contributions do not include additions to
the Program which: (i) are separate modules of software distributed in
conjunction with the Program under their own license agreement, and (ii) are
not derivative works of the Program.
"Contributor" means any person or entity that distributes the Program.
"Licensed Patents " mean patent claims licensable by a Contributor which are
necessarily infringed by the use or sale of its Contribution alone or when
combined with the Program.
"Program" means the Contributions distributed in accordance with this Agreement.
"Recipient" means anyone who receives the Program under this Agreement,
including all Contributors.
2. GRANT OF RIGHTS
a) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free copyright license to
reproduce, prepare derivative works of, publicly display, publicly perform,
distribute and sublicense the Contribution of such Contributor, if any, and
such derivative works, in source code and object code form.
b) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free patent license under
Licensed Patents to make, use, sell, offer to sell, import and otherwise
transfer the Contribution of such Contributor, if any, in source code and
object code form. This patent license shall apply to the combination of the
Contribution and the Program if, at the time the Contribution is added by the
Contributor, such addition of the Contribution causes such combination to be
covered by the Licensed Patents. The patent license shall not apply to any
other combinations which include the Contribution. No hardware per se is
licensed hereunder.
c) Recipient understands that although each Contributor grants the
licenses to its Contributions set forth herein, no assurances are provided by
any Contributor that the Program does not infringe the patent or other
intellectual property rights of any other entity. Each Contributor disclaims
any liability to Recipient for claims brought by any other entity based on
infringement of intellectual property rights or otherwise. As a condition to
exercising the rights and licenses granted hereunder, each Recipient hereby
assumes sole responsibility to secure any other intellectual property rights
needed, if any. For example, if a third party patent license is required to
allow Recipient to distribute the Program, it is Recipient's responsibility to
acquire that license before distributing the Program.
d) Each Contributor represents that to its knowledge it has sufficient
copyright rights in its Contribution, if any, to grant the copyright license
set forth in this Agreement.
3. REQUIREMENTS
A Contributor may choose to distribute the Program in object code form under
its own license agreement, provided that:
a) it complies with the terms and conditions of this Agreement; and
b) its license agreement:
i) effectively disclaims on behalf of all Contributors all warranties and
conditions, express and implied, including warranties or conditions of title
and non-infringement, and implied warranties or conditions of merchantability
and fitness for a particular purpose;
ii) effectively excludes on behalf of all Contributors all liability for
damages, including direct, indirect, special, incidental and consequential
damages, such as lost profits;
iii) states that any provisions which differ from this Agreement are
offered by that Contributor alone and not by any other party; and
iv) states that source code for the Program is available from such
Contributor, and informs licensees how to obtain it in a reasonable manner on
or through a medium customarily used for software exchange.
When the Program is made available in source code form:
a) it must be made available under this Agreement; and
b) a copy of this Agreement must be included with each copy of the
Program.
Contributors may not remove or alter any copyright notices contained within the
Program.
Each Contributor must identify itself as the originator of its Contribution, if
any, in a manner that reasonably allows subsequent Recipients to identify the
originator of the Contribution.
4. COMMERCIAL DISTRIBUTION
Commercial distributors of software may accept certain responsibilities with
respect to end users, business partners and the like. While this license is
intended to facilitate the commercial use of the Program, the Contributor who
includes the Program in a commercial product offering should do so in a manner
which does not create potential liability for other Contributors. Therefore, if
a Contributor includes the Program in a commercial product offering, such
Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
every other Contributor ("Indemnified Contributor") against any losses, damages
and costs (collectively "Losses") arising from claims, lawsuits and other legal
actions brought by a third party against the Indemnified Contributor to the
extent caused by the acts or omissions of such Commercial Contributor in
connection with its distribution of the Program in a commercial product
offering. The obligations in this section do not apply to any claims or Losses
relating to any actual or alleged intellectual property infringement. In order
to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
Contributor in writing of such claim, and b) allow the Commercial Contributor
to control, and cooperate with the Commercial Contributor in, the defense and
any related settlement negotiations. The Indemnified Contributor may
participate in any such claim at its own expense.
For example, a Contributor might include the Program in a commercial product
offering, Product X. That Contributor is then a Commercial Contributor. If that
Commercial Contributor then makes performance claims, or offers warranties
related to Product X, those performance claims and warranties are such
Commercial Contributor's responsibility alone. Under this section, the
Commercial Contributor would have to defend claims against the other
Contributors related to those performance claims and warranties, and if a court
requires any other Contributor to pay any damages as a result, the Commercial
Contributor must pay those damages.
5. NO WARRANTY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED 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. Each
Recipient is solely responsible for determining the appropriateness of using
and distributing the Program and assumes all risks associated with its exercise
of rights under this Agreement, including but not limited to the risks and
costs of program errors, compliance with applicable laws, damage to or loss of
data, programs or equipment, and unavailability or interruption of operations.
6. DISCLAIMER OF LIABILITY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. GENERAL
If any provision of this Agreement is invalid or unenforceable under applicable
law, it shall not affect the validity or enforceability of the remainder of the
terms of this Agreement, and without further action by the parties hereto, such
provision shall be reformed to the minimum extent necessary to make such
provision valid and enforceable.
If Recipient institutes patent litigation against a Contributor with respect to
a patent applicable to software (including a cross-claim or counterclaim in a
lawsuit), then any patent licenses granted by that Contributor to such
Recipient under this Agreement shall terminate as of the date such litigation
is filed. In addition, if Recipient institutes patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging that the
Program itself (excluding combinations of the Program with other software or
hardware) infringes such Recipient's patent(s), then such Recipient's rights
granted under Section 2(b) shall terminate as of the date such litigation is
filed.
All Recipient's rights under this Agreement shall terminate if it fails to
comply with any of the material terms or conditions of this Agreement and does
not cure such failure in a reasonable period of time after becoming aware of
such noncompliance. If all Recipient's rights under this Agreement terminate,
Recipient agrees to cease use and distribution of the Program as soon as
reasonably practicable. However, Recipient's obligations under this Agreement
and any licenses granted by Recipient relating to the Program shall continue
and survive.
Everyone is permitted to copy and distribute copies of this Agreement, but in
order to avoid inconsistency the Agreement is copyrighted and may only be
modified in the following manner. The Agreement Steward reserves the right to
publish new versions (including revisions) of this Agreement from time to time.
No one other than the Agreement Steward has the right to modify this Agreement.
IBM is the initial Agreement Steward. IBM may assign the responsibility to
serve as the Agreement Steward to a suitable separate entity. Each new version
of the Agreement will be given a distinguishing version number. The Program
(including Contributions) may always be distributed subject to the version of
the Agreement under which it was received. In addition, after a new version of
the Agreement is published, Contributor may elect to distribute the Program
(including its Contributions) under the new version. Except as expressly stated
in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
the intellectual property of any Contributor under this Agreement, whether
expressly, by implication, estoppel or otherwise. All rights in the Program not
expressly granted under this Agreement are reserved.
This Agreement is governed by the laws of the State of New York and the
intellectual property laws of the United States of America. No party to this
Agreement will bring a legal action under this Agreement more than one year
after the cause of action arose. Each party waives its rights to a jury trial
in any resulting litigation.
limitations under the License.

7
NOTICE
View File

@@ -3,10 +3,3 @@ Copyright 2011 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org)
This product also includes the following third-party components:
* Junit (framework/libs/junit-4.10.jar) (http://junit.sourceforge.net)
Licensed under the Common Public License
http://junit.sourceforge.net/cpl-v10.html

View File

@@ -23,7 +23,7 @@ Requires
Building
---
To create your phonegap.jar, run in the framework directory:
To create your cordova.jar, run in the framework directory:
android update project -p . -t android-15
ant jar
@@ -45,9 +45,9 @@ Project Commands
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
---
@@ -60,11 +60,11 @@ 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:
---
@@ -82,7 +82,7 @@ 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)

View File

@@ -1 +1 @@
1.4.1
1.7.0rc1

View File

@@ -1,4 +1,4 @@
#! /bin/sh
./bin/create
cd ./example && ./phonegap/debug && ./phonegap/log
cd ./example && ./cordova/debug && ./cordova/log

View File

@@ -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

View File

@@ -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,27 @@ 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
# copy in res/xml
cp ./framework/res/xml/cordova.xml $PROJECT_PATH/.cordova/android/cordova.xml
cp ./framework/res/xml/plugins.xml $PROJECT_PATH/.cordova/android/plugins.xml
# app properties
cat > $PROJECT_PATH/.phonegap/config <<eom
cat > $PROJECT_PATH/.cordova/config <<eom
VERSION=$VERSION
PROJECT_PATH=$PROJECT_PATH
PACKAGE=$PACKAGE
@@ -43,4 +47,4 @@ ACTIVITY=$ACTIVITY
TARGET=$TARGET
eom
(cd $PROJECT_PATH && ./phonegap/create)
(cd $PROJECT_PATH && ./cordova/create)

View File

@@ -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');

View File

@@ -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" />

View File

@@ -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!

View File

@@ -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,17 +16,22 @@ 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 res/xml
mkdir ./res/xml
cp ./.cordova/android/cordova.xml ./res/xml
cp ./.cordova/android/plugins.xml ./res/xml
# 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 -e "s/__ACTIVITY__/${ACTIVITY}/g"

View File

@@ -1,9 +1,9 @@
#! /bin/sh
. ./.phonegap/config
. ./.cordova/config
# if there are no devices listed then emulate
ant clean
ant debug install
adb shell am start -n $PACKAGE/$PACKAGE.$ACTIVITY

View File

@@ -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
{

View File

@@ -2,13 +2,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="__PACKAGE__" android:versionName="1.1" android:versionCode="5">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
@@ -27,24 +27,17 @@
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:debuggable="true">
<activity android:name="__ACTIVITY__" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
</intent-filter>
android:debuggable="true">
<activity android:name="__ACTIVITY__" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5" />
<uses-sdk android:minSdkVersion="5" />
</manifest>

View File

@@ -4,13 +4,13 @@
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>PhoneGap</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="phonegap-1.4.1.js"></script>
<script type="text/javascript" charset="utf-8" src="main.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.7.0rc1.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Welcome to PhoneGap!</h1>
<h1>Welcome to Cordova!</h1>
<h2>this file is located at assets/www/index.html</h2>
<div id="info">
<h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
@@ -25,14 +25,14 @@
</dl>
<a href="#" class="btn large" onclick="toggleAccel();">Toggle Accelerometer</a>
<a href="#" class="btn large" onclick="getLocation();">Get Location</a>
<a href="tel:411" class="btn large">Call 411</a>
<a href="tel:411" class="btn large">Call 411</a>
<a href="#" class="btn large" onclick="beep();">Beep</a>
<a href="#" class="btn large" onclick="vibrate();">Vibrate</a>
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
<a href="#" class="btn large" onclick="get_contacts();return false;">Get Phone's Contacts</a>
<a href="#" class="btn large" onclick="check_network();return false;">Check Network</a>
<dl>
<dt>Compass Heading:</dt><dd id="h">Off</dd>
<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;">

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -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>

View File

@@ -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

View File

@@ -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()

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>PhoneGap</name>
<name>Cordova</name>
<comment></comment>
<projects>
</projects>

View 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"
@@ -39,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>

View File

@@ -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

View File

@@ -1,137 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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();
}
});
}

View File

@@ -1,89 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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", []);
};
/**
* Exit and terminate the application.
*/
App.prototype.exitApp = function() {
return PhoneGap.exec(null, null, "App", "exitApp", []);
};
PhoneGap.addConstructor(function() {
navigator.app = new App();
});
}());
}

View File

@@ -1,134 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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") {
if (me._batteryListener.indexOf(handler) === -1) {
me._batteryListener.push(handler);
}
} else if (eventType === "batterylow") {
if (me._lowListener.indexOf(handler) === -1) {
me._lowListener.push(handler);
}
} else if (eventType === "batterycritical") {
if (me._criticalListener.indexOf(handler) === -1) {
me._criticalListener.push(handler);
}
}
} else {
var pos = -1;
// Remove the event listener from the proper array
if (eventType === "batterystatus") {
pos = me._batteryListener.indexOf(handler);
if (pos > -1) {
me._batteryListener.splice(pos, 1);
}
} else if (eventType === "batterylow") {
pos = me._lowListener.indexOf(handler);
if (pos > -1) {
me._lowListener.splice(pos, 1);
}
} else if (eventType === "batterycritical") {
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;
var level = info.level;
if (me._level !== level || me._isPlugged !== info.isPlugged) {
// Fire batterystatus event
PhoneGap.fireWindowEvent("batterystatus", info);
// Fire low battery event
if (level === 20 || level === 5) {
if (level === 20) {
PhoneGap.fireWindowEvent("batterylow", info);
}
else {
PhoneGap.fireWindowEvent("batterycritical", info);
}
}
}
me._level = 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);
}
});
}

View File

@@ -1,168 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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.FILE_URI;
}
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();
}
});
}

View File

@@ -1,199 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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.capture === "undefined") {
navigator.device.capture = window.device.capture = new Capture();
}
});
}

View File

@@ -1,153 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
if (!PhoneGap.hasResource("compass")) {
PhoneGap.addResource("compass");
var CompassError = function(){
this.code = null;
};
// Capture error codes
CompassError.COMPASS_INTERNAL_ERR = 0;
CompassError.COMPASS_NOT_SUPPORTED = 20;
var 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();
}
});
}

View File

@@ -1,321 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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();
}
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// 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();
}
});
}

View File

@@ -1,83 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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", []);
};
PhoneGap.addConstructor(function() {
if (typeof navigator.device === "undefined") {
navigator.device = window.device = new Device();
}
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,111 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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]);
};
/**
* Downloads a file form a given URL and saves it to the specified directory.
* @param source {String} URL of the server to receive the file
* @param target {String} Full path of the file on the device
* @param successCallback (Function} Callback to be invoked when upload has completed
* @param errorCallback {Function} Callback to be invoked upon error
*/
FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'download', [source, target]);
};
/**
* 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;
};
}

View File

@@ -1,209 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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;
}
});
}

View File

@@ -1,19 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

View File

@@ -1,233 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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;
}
};
}

View File

@@ -1,100 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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 = {};
}
if (typeof navigator.network.connection === "undefined") {
navigator.network.connection = new Connection();
}
});
}

View File

@@ -1,133 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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();
}
});
}

View File

@@ -1,922 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// Version 1.2.0
if (typeof PhoneGap === "undefined") {
/**
* The order of events during page load and PhoneGap startup is as follows:
*
* onDOMContentLoaded Internal event that is received when the web page is loaded and parsed.
* window.onload Body onload event.
* onNativeReady Internal event that indicates the PhoneGap native side is ready.
* onPhoneGapInit Internal event that kicks off creation of all PhoneGap JavaScript objects (runs constructors).
* onPhoneGapReady Internal event fired when all PhoneGap JavaScript objects have been created
* onPhoneGapInfoReady Internal event fired when device properties are available
* onDeviceReady User event fired to indicate that PhoneGap is ready
* onResume User event fired to indicate a start/resume lifecycle event
* onPause User event fired to indicate a pause lifecycle event
* onDestroy Internal event fired when app is being destroyed (User should use window.onunload event, not this one).
*
* The only PhoneGap events that user code should register for are:
* deviceready PhoneGap native code is initialized and PhoneGap APIs can be called from JavaScript
* pause App has moved to background
* resume App has returned to foreground
*
* Listeners can be registered as:
* document.addEventListener("deviceready", myDeviceReadyListener, false);
* document.addEventListener("resume", myResumeListener, false);
* document.addEventListener("pause", myPauseListener, false);
*
* The DOM lifecycle events should be used for saving and restoring state
* window.onload
* window.onunload
*/
/**
* This represents the PhoneGap API itself, and provides a global namespace for accessing
* information about the state of PhoneGap.
* @class
*/
var PhoneGap = {
documentEventHandler: {}, // Collection of custom document event handlers
windowEventHandler: {} // Collection of custom window event handlers
};
/**
* List of resource files loaded by PhoneGap.
* This is used to ensure JS and other files are loaded only once.
*/
PhoneGap.resources = {base: true};
/**
* Determine if resource has been loaded by PhoneGap
*
* @param name
* @return
*/
PhoneGap.hasResource = function(name) {
return PhoneGap.resources[name];
};
/**
* Add a resource to list of loaded resources by PhoneGap
*
* @param name
*/
PhoneGap.addResource = function(name) {
PhoneGap.resources[name] = true;
};
/**
* Custom pub-sub channel that can have functions subscribed to it
* @constructor
*/
PhoneGap.Channel = function (type)
{
this.type = type;
this.handlers = {};
this.guid = 0;
this.fired = false;
this.enabled = true;
};
/**
* Subscribes the given function to the channel. Any time that
* Channel.fire is called so too will the function.
* Optionally specify an execution context for the function
* and a guid that can be used to stop subscribing to the channel.
* Returns the guid.
*/
PhoneGap.Channel.prototype.subscribe = function(f, c, g) {
// need a function to call
if (f === null) { return; }
var func = f;
if (typeof c === "object" && typeof f === "function") { func = PhoneGap.close(c, f); }
g = g || func.observer_guid || f.observer_guid || this.guid++;
func.observer_guid = g;
f.observer_guid = g;
this.handlers[g] = func;
return g;
};
/**
* Like subscribe but the function is only called once and then it
* auto-unsubscribes itself.
*/
PhoneGap.Channel.prototype.subscribeOnce = function(f, c) {
var g = null;
var _this = this;
var m = function() {
f.apply(c || null, arguments);
_this.unsubscribe(g);
};
if (this.fired) {
if (typeof c === "object" && typeof f === "function") { f = PhoneGap.close(c, f); }
f.apply(this, this.fireArgs);
} else {
g = this.subscribe(m);
}
return g;
};
/**
* Unsubscribes the function with the given guid from the channel.
*/
PhoneGap.Channel.prototype.unsubscribe = function(g) {
if (typeof g === "function") { g = g.observer_guid; }
this.handlers[g] = null;
delete this.handlers[g];
};
/**
* Calls all functions subscribed to this channel.
*/
PhoneGap.Channel.prototype.fire = function(e) {
if (this.enabled) {
var fail = false;
var item, handler, rv;
for (item in this.handlers) {
if (this.handlers.hasOwnProperty(item)) {
handler = this.handlers[item];
if (typeof handler === "function") {
rv = (handler.apply(this, arguments) === false);
fail = fail || rv;
}
}
}
this.fired = true;
this.fireArgs = arguments;
return !fail;
}
return true;
};
/**
* Calls the provided function only after all of the channels specified
* have been fired.
*/
PhoneGap.Channel.join = function(h, c) {
var i = c.length;
var f = function() {
if (!(--i)) {
h();
}
};
var len = i;
var j;
for (j=0; j<len; j++) {
if (!c[j].fired) {
c[j].subscribeOnce(f);
}
else {
i--;
}
}
if (!i) {
h();
}
};
/**
* Add an initialization function to a queue that ensures it will run and initialize
* application constructors only once PhoneGap has been initialized.
* @param {Function} func The function callback you want run once PhoneGap is initialized
*/
PhoneGap.addConstructor = function(func) {
PhoneGap.onPhoneGapInit.subscribeOnce(function() {
try {
func();
} catch(e) {
console.log("Failed to run constructor: " + e);
}
});
};
/**
* Plugins object
*/
if (!window.plugins) {
window.plugins = {};
}
/**
* Adds a plugin object to window.plugins.
* The plugin is accessed using window.plugins.<name>
*
* @param name The plugin name
* @param obj The plugin object
*/
PhoneGap.addPlugin = function(name, obj) {
if (!window.plugins[name]) {
window.plugins[name] = obj;
}
else {
console.log("Error: Plugin "+name+" already exists.");
}
};
/**
* onDOMContentLoaded channel is fired when the DOM content
* of the page has been parsed.
*/
PhoneGap.onDOMContentLoaded = new PhoneGap.Channel('onDOMContentLoaded');
/**
* onNativeReady channel is fired when the PhoneGap native code
* has been initialized.
*/
PhoneGap.onNativeReady = new PhoneGap.Channel('onNativeReady');
/**
* onPhoneGapInit channel is fired when the web page is fully loaded and
* PhoneGap native code has been initialized.
*/
PhoneGap.onPhoneGapInit = new PhoneGap.Channel('onPhoneGapInit');
/**
* onPhoneGapReady channel is fired when the JS PhoneGap objects have been created.
*/
PhoneGap.onPhoneGapReady = new PhoneGap.Channel('onPhoneGapReady');
/**
* onPhoneGapInfoReady channel is fired when the PhoneGap device properties
* has been set.
*/
PhoneGap.onPhoneGapInfoReady = new PhoneGap.Channel('onPhoneGapInfoReady');
/**
* onPhoneGapConnectionReady channel is fired when the PhoneGap connection properties
* has been set.
*/
PhoneGap.onPhoneGapConnectionReady = new PhoneGap.Channel('onPhoneGapConnectionReady');
/**
* onDestroy channel is fired when the PhoneGap native code
* is destroyed. It is used internally.
* Window.onunload should be used by the user.
*/
PhoneGap.onDestroy = new PhoneGap.Channel('onDestroy');
PhoneGap.onDestroy.subscribeOnce(function() {
PhoneGap.shuttingDown = true;
});
PhoneGap.shuttingDown = false;
// _nativeReady is global variable that the native side can set
// to signify that the native code is ready. It is a global since
// it may be called before any PhoneGap JS is ready.
if (typeof _nativeReady !== 'undefined') { PhoneGap.onNativeReady.fire(); }
/**
* onDeviceReady is fired only after all PhoneGap objects are created and
* the device properties are set.
*/
PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady');
// Array of channels that must fire before "deviceready" is fired
PhoneGap.deviceReadyChannelsArray = [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady, PhoneGap.onPhoneGapConnectionReady];
// Hashtable of user defined channels that must also fire before "deviceready" is fired
PhoneGap.deviceReadyChannelsMap = {};
/**
* Indicate that a feature needs to be initialized before it is ready to be used.
* This holds up PhoneGap's "deviceready" event until the feature has been initialized
* and PhoneGap.initComplete(feature) is called.
*
* @param feature {String} The unique feature name
*/
PhoneGap.waitForInitialization = function(feature) {
if (feature) {
var channel = new PhoneGap.Channel(feature);
PhoneGap.deviceReadyChannelsMap[feature] = channel;
PhoneGap.deviceReadyChannelsArray.push(channel);
}
};
/**
* Indicate that initialization code has completed and the feature is ready to be used.
*
* @param feature {String} The unique feature name
*/
PhoneGap.initializationComplete = function(feature) {
var channel = PhoneGap.deviceReadyChannelsMap[feature];
if (channel) {
channel.fire();
}
};
/**
* Create all PhoneGap objects once page has fully loaded and native side is ready.
*/
PhoneGap.Channel.join(function() {
// Start listening for XHR callbacks
setTimeout(function() {
if (PhoneGap.UsePolling) {
PhoneGap.JSCallbackPolling();
}
else {
var polling = prompt("usePolling", "gap_callbackServer:");
PhoneGap.UsePolling = polling;
if (polling == "true") {
PhoneGap.UsePolling = true;
PhoneGap.JSCallbackPolling();
}
else {
PhoneGap.UsePolling = false;
PhoneGap.JSCallback();
}
}
}, 1);
// Run PhoneGap constructors
PhoneGap.onPhoneGapInit.fire();
// Fire event to notify that all objects are created
PhoneGap.onPhoneGapReady.fire();
// Fire onDeviceReady event once all constructors have run and PhoneGap info has been
// received from native side, and any user defined initialization channels.
PhoneGap.Channel.join(function() {
// Let native code know we are inited on JS side
prompt("", "gap_init:");
PhoneGap.onDeviceReady.fire();
}, PhoneGap.deviceReadyChannelsArray);
}, [ PhoneGap.onDOMContentLoaded, PhoneGap.onNativeReady ]);
// Listen for DOMContentLoaded and notify our channel subscribers
document.addEventListener('DOMContentLoaded', function() {
PhoneGap.onDOMContentLoaded.fire();
}, false);
// Intercept calls to document.addEventListener and watch for deviceready
PhoneGap.m_document_addEventListener = document.addEventListener;
// Intercept calls to window.addEventListener
PhoneGap.m_window_addEventListener = window.addEventListener;
/**
* Add a custom window event handler.
*
* @param {String} event The event name that callback handles
* @param {Function} callback The event handler
*/
PhoneGap.addWindowEventHandler = function(event, callback) {
PhoneGap.windowEventHandler[event] = callback;
};
/**
* Add a custom document event handler.
*
* @param {String} event The event name that callback handles
* @param {Function} callback The event handler
*/
PhoneGap.addDocumentEventHandler = function(event, callback) {
PhoneGap.documentEventHandler[event] = callback;
};
/**
* Intercept adding document event listeners and handle our own
*
* @param {Object} evt
* @param {Function} handler
* @param capture
*/
document.addEventListener = function(evt, handler, capture) {
var e = evt.toLowerCase();
if (e === 'deviceready') {
PhoneGap.onDeviceReady.subscribeOnce(handler);
}
else {
// If subscribing to Android backbutton
if (e === 'backbutton') {
PhoneGap.exec(null, null, "App", "overrideBackbutton", [true]);
}
// If subscribing to an event that is handled by a plugin
else if (typeof PhoneGap.documentEventHandler[e] !== "undefined") {
if (PhoneGap.documentEventHandler[e](e, handler, true)) {
return; // Stop default behavior
}
}
PhoneGap.m_document_addEventListener.call(document, evt, handler, capture);
}
};
/**
* Intercept adding window event listeners and handle our own
*
* @param {Object} evt
* @param {Function} handler
* @param capture
*/
window.addEventListener = function(evt, handler, capture) {
var e = evt.toLowerCase();
// If subscribing to an event that is handled by a plugin
if (typeof PhoneGap.windowEventHandler[e] !== "undefined") {
if (PhoneGap.windowEventHandler[e](e, handler, true)) {
return; // Stop default behavior
}
}
PhoneGap.m_window_addEventListener.call(window, evt, handler, capture);
};
// Intercept calls to document.removeEventListener and watch for events that
// are generated by PhoneGap native code
PhoneGap.m_document_removeEventListener = document.removeEventListener;
// Intercept calls to window.removeEventListener
PhoneGap.m_window_removeEventListener = window.removeEventListener;
/**
* Intercept removing document event listeners and handle our own
*
* @param {Object} evt
* @param {Function} handler
* @param capture
*/
document.removeEventListener = function(evt, handler, capture) {
var e = evt.toLowerCase();
// If unsubscribing to Android backbutton
if (e === 'backbutton') {
PhoneGap.exec(null, null, "App", "overrideBackbutton", [false]);
}
// If unsubcribing from an event that is handled by a plugin
if (typeof PhoneGap.documentEventHandler[e] !== "undefined") {
if (PhoneGap.documentEventHandler[e](e, handler, false)) {
return; // Stop default behavior
}
}
PhoneGap.m_document_removeEventListener.call(document, evt, handler, capture);
};
/**
* Intercept removing window event listeners and handle our own
*
* @param {Object} evt
* @param {Function} handler
* @param capture
*/
window.removeEventListener = function(evt, handler, capture) {
var e = evt.toLowerCase();
// If unsubcribing from an event that is handled by a plugin
if (typeof PhoneGap.windowEventHandler[e] !== "undefined") {
if (PhoneGap.windowEventHandler[e](e, handler, false)) {
return; // Stop default behavior
}
}
PhoneGap.m_window_removeEventListener.call(window, evt, handler, capture);
};
/**
* Method to fire document event
*
* @param {String} type The event type to fire
* @param {Object} data Data to send with event
*/
PhoneGap.fireDocumentEvent = function(type, data) {
var e = document.createEvent('Events');
e.initEvent(type);
if (data) {
for (var i in data) {
e[i] = data[i];
}
}
document.dispatchEvent(e);
};
/**
* Method to fire window event
*
* @param {String} type The event type to fire
* @param {Object} data Data to send with event
*/
PhoneGap.fireWindowEvent = function(type, data) {
var e = document.createEvent('Events');
e.initEvent(type);
if (data) {
for (var i in data) {
e[i] = data[i];
}
}
window.dispatchEvent(e);
};
/**
* Does a deep clone of the object.
*
* @param obj
* @return {Object}
*/
PhoneGap.clone = function(obj) {
var i, retVal;
if(!obj) {
return obj;
}
if(obj instanceof Array){
retVal = [];
for(i = 0; i < obj.length; ++i){
retVal.push(PhoneGap.clone(obj[i]));
}
return retVal;
}
if (typeof obj === "function") {
return obj;
}
if(!(obj instanceof Object)){
return obj;
}
if (obj instanceof Date) {
return obj;
}
retVal = {};
for(i in obj){
if(!(i in retVal) || retVal[i] !== obj[i]) {
retVal[i] = PhoneGap.clone(obj[i]);
}
}
return retVal;
};
PhoneGap.callbackId = 0;
PhoneGap.callbacks = {};
PhoneGap.callbackStatus = {
NO_RESULT: 0,
OK: 1,
CLASS_NOT_FOUND_EXCEPTION: 2,
ILLEGAL_ACCESS_EXCEPTION: 3,
INSTANTIATION_EXCEPTION: 4,
MALFORMED_URL_EXCEPTION: 5,
IO_EXCEPTION: 6,
INVALID_ACTION: 7,
JSON_EXCEPTION: 8,
ERROR: 9
};
/**
* Execute a PhoneGap command. It is up to the native side whether this action is synch or async.
* The native side can return:
* Synchronous: PluginResult object as a JSON string
* Asynchrounous: Empty string ""
* If async, the native side will PhoneGap.callbackSuccess or PhoneGap.callbackError,
* depending upon the result of the action.
*
* @param {Function} success The success callback
* @param {Function} fail The fail callback
* @param {String} service The name of the service to use
* @param {String} action Action to be run in PhoneGap
* @param {Array.<String>} [args] Zero or more arguments to pass to the method
*/
PhoneGap.exec = function(success, fail, service, action, args) {
try {
var callbackId = service + PhoneGap.callbackId++;
if (success || fail) {
PhoneGap.callbacks[callbackId] = {success:success, fail:fail};
}
var r = prompt(JSON.stringify(args), "gap:"+JSON.stringify([service, action, callbackId, true]));
// If a result was returned
if (r.length > 0) {
eval("var v="+r+";");
// If status is OK, then return value back to caller
if (v.status === PhoneGap.callbackStatus.OK) {
// If there is a success callback, then call it now with
// returned value
if (success) {
try {
success(v.message);
} catch (e) {
console.log("Error in success callback: " + callbackId + " = " + e);
}
// Clear callback if not expecting any more results
if (!v.keepCallback) {
delete PhoneGap.callbacks[callbackId];
}
}
return v.message;
}
// If no result
else if (v.status === PhoneGap.callbackStatus.NO_RESULT) {
// Clear callback if not expecting any more results
if (!v.keepCallback) {
delete PhoneGap.callbacks[callbackId];
}
}
// If error, then display error
else {
console.log("Error: Status="+v.status+" Message="+v.message);
// If there is a fail callback, then call it now with returned value
if (fail) {
try {
fail(v.message);
}
catch (e1) {
console.log("Error in error callback: "+callbackId+" = "+e1);
}
// Clear callback if not expecting any more results
if (!v.keepCallback) {
delete PhoneGap.callbacks[callbackId];
}
}
return null;
}
}
} catch (e2) {
console.log("Error: "+e2);
}
};
/**
* Called by native code when returning successful result from an action.
*
* @param callbackId
* @param args
*/
PhoneGap.callbackSuccess = function(callbackId, args) {
if (PhoneGap.callbacks[callbackId]) {
// If result is to be sent to callback
if (args.status === PhoneGap.callbackStatus.OK) {
try {
if (PhoneGap.callbacks[callbackId].success) {
PhoneGap.callbacks[callbackId].success(args.message);
}
}
catch (e) {
console.log("Error in success callback: "+callbackId+" = "+e);
}
}
// Clear callback if not expecting any more results
if (!args.keepCallback) {
delete PhoneGap.callbacks[callbackId];
}
}
};
/**
* Called by native code when returning error result from an action.
*
* @param callbackId
* @param args
*/
PhoneGap.callbackError = function(callbackId, args) {
if (PhoneGap.callbacks[callbackId]) {
try {
if (PhoneGap.callbacks[callbackId].fail) {
PhoneGap.callbacks[callbackId].fail(args.message);
}
}
catch (e) {
console.log("Error in error callback: "+callbackId+" = "+e);
}
// Clear callback if not expecting any more results
if (!args.keepCallback) {
delete PhoneGap.callbacks[callbackId];
}
}
};
PhoneGap.JSCallbackPort = null;
PhoneGap.JSCallbackToken = null;
/**
* This is only for Android.
*
* Internal function that uses XHR to call into PhoneGap Java code and retrieve
* any JavaScript code that needs to be run. This is used for callbacks from
* Java to JavaScript.
*/
PhoneGap.JSCallback = function() {
// Exit if shutting down app
if (PhoneGap.shuttingDown) {
return;
}
// If polling flag was changed, start using polling from now on
if (PhoneGap.UsePolling) {
PhoneGap.JSCallbackPolling();
return;
}
var xmlhttp = new XMLHttpRequest();
// Callback function when XMLHttpRequest is ready
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState === 4){
// Exit if shutting down app
if (PhoneGap.shuttingDown) {
return;
}
// If callback has JavaScript statement to execute
if (xmlhttp.status === 200) {
// Need to url decode the response
var msg = decodeURIComponent(xmlhttp.responseText);
setTimeout(function() {
try {
var t = eval(msg);
}
catch (e) {
// If we're getting an error here, seeing the message will help in debugging
console.log("JSCallback: Message from Server: " + msg);
console.log("JSCallback Error: "+e);
}
}, 1);
setTimeout(PhoneGap.JSCallback, 1);
}
// If callback ping (used to keep XHR request from timing out)
else if (xmlhttp.status === 404) {
setTimeout(PhoneGap.JSCallback, 10);
}
// If security error
else if (xmlhttp.status === 403) {
console.log("JSCallback Error: Invalid token. Stopping callbacks.");
}
// If server is stopping
else if (xmlhttp.status === 503) {
console.log("JSCallback Server Closed: Stopping callbacks.");
}
// If request wasn't GET
else if (xmlhttp.status === 400) {
console.log("JSCallback Error: Bad request. Stopping callbacks.");
}
// If error, revert to polling
else {
console.log("JSCallback Error: Request failed.");
PhoneGap.UsePolling = true;
PhoneGap.JSCallbackPolling();
}
}
};
if (PhoneGap.JSCallbackPort === null) {
PhoneGap.JSCallbackPort = prompt("getPort", "gap_callbackServer:");
}
if (PhoneGap.JSCallbackToken === null) {
PhoneGap.JSCallbackToken = prompt("getToken", "gap_callbackServer:");
}
xmlhttp.open("GET", "http://127.0.0.1:"+PhoneGap.JSCallbackPort+"/"+PhoneGap.JSCallbackToken , true);
xmlhttp.send();
};
/**
* The polling period to use with JSCallbackPolling.
* This can be changed by the application. The default is 50ms.
*/
PhoneGap.JSCallbackPollingPeriod = 50;
/**
* Flag that can be set by the user to force polling to be used or force XHR to be used.
*/
PhoneGap.UsePolling = false; // T=use polling, F=use XHR
/**
* This is only for Android.
*
* Internal function that uses polling to call into PhoneGap Java code and retrieve
* any JavaScript code that needs to be run. This is used for callbacks from
* Java to JavaScript.
*/
PhoneGap.JSCallbackPolling = function() {
// Exit if shutting down app
if (PhoneGap.shuttingDown) {
return;
}
// If polling flag was changed, stop using polling from now on
if (!PhoneGap.UsePolling) {
PhoneGap.JSCallback();
return;
}
var msg = prompt("", "gap_poll:");
if (msg) {
setTimeout(function() {
try {
var t = eval(""+msg);
}
catch (e) {
console.log("JSCallbackPolling: Message from Server: " + msg);
console.log("JSCallbackPolling Error: "+e);
}
}, 1);
setTimeout(PhoneGap.JSCallbackPolling, 1);
}
else {
setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod);
}
};
/**
* Create a UUID
*
* @return {String}
*/
PhoneGap.createUUID = function() {
return PhoneGap.UUIDcreatePart(4) + '-' +
PhoneGap.UUIDcreatePart(2) + '-' +
PhoneGap.UUIDcreatePart(2) + '-' +
PhoneGap.UUIDcreatePart(2) + '-' +
PhoneGap.UUIDcreatePart(6);
};
PhoneGap.UUIDcreatePart = function(length) {
var uuidpart = "";
var i, uuidchar;
for (i=0; i<length; i++) {
uuidchar = parseInt((Math.random() * 256),0).toString(16);
if (uuidchar.length === 1) {
uuidchar = "0" + uuidchar;
}
uuidpart += uuidchar;
}
return uuidpart;
};
PhoneGap.close = function(context, func, params) {
if (typeof params === 'undefined') {
return function() {
return func.apply(context, arguments);
};
} else {
return function() {
return func.apply(context, params);
};
}
};
/**
* Load a JavaScript file after page has loaded.
*
* @param {String} jsfile The url of the JavaScript file to load.
* @param {Function} successCallback The callback to call when the file has been loaded.
*/
PhoneGap.includeJavascript = function(jsfile, successCallback) {
var id = document.getElementsByTagName("head")[0];
var el = document.createElement('script');
el.type = 'text/javascript';
if (typeof successCallback === 'function') {
el.onload = successCallback;
}
el.src = jsfile;
id.appendChild(el);
};
}

View File

@@ -1,100 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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;
}

View File

@@ -1,439 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* This 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") || (window.localStorage == null)) {
navigator.localStorage = window.localStorage = new CupcakeLocalStorage();
PhoneGap.waitForInitialization("cupcakeStorage");
}
});
}

View File

@@ -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.4.1.js"></script>
<script src="cordova-1.7.0rc1.js"></script>
</head>
<body>

View File

@@ -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,78 +108,43 @@
-->
<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">
<filelist dir="assets/js" files="phonegap.js.base,device.js"/>
<fileset dir="assets/js" includes="*.js" excludes="phonegap.js.base,device.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" /> -->
<fileset file="../bin/templates/project/cordova/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>
<!-- tests for Java files -->
<property name="test.dir" location="test/com/phonegap" />
<property name="test.dir" location="test/org/apache/cordova" />
<path id="test.classpath">
<!-- requires both junit and phonegap -->
<!-- requires both junit and cordova -->
<pathelement location="libs/junit-4.10.jar" />
<pathelement location="phonegap-${version}.jar" />
<pathelement location="cordova-${version}.jar" />
<pathelement location="${test.dir}" />
</path>
@@ -184,10 +167,10 @@
</junit>
</target>
<target name="phonegap_debug" depends="build-javascript, debug">
<target name="cordova_debug" depends="build-javascript, debug">
</target>
<target name="phonegap_release" depends="build-javascript, release">
<target name="cordova_release" depends="build-javascript, release">
</target>
</project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -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"

View File

@@ -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>

View 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>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<phonegap>
<!--
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" />
</phonegap>

View File

@@ -1,19 +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="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"/>
<plugin name="App" value="org.apache.cordova.App"/>
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
<plugin name="Device" value="org.apache.cordova.Device"/>
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
<plugin name="File" value="org.apache.cordova.FileUtils"/>
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage"/>
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
<plugin name="Capture" value="org.apache.cordova.Capture"/>
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
</plugins>

View File

@@ -1,113 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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);
}
}
}

View File

@@ -1,366 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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;
}
}
}

View File

@@ -1,16 +0,0 @@
package com.phonegap;
// represents the <preference> element from the W3C config.xml spec
// see http://www.w3.org/TR/widgets/#the-preference-element-and-its-attributes
public class PreferenceNode {
public String name;
public String value;
public boolean readonly;
// constructor
public PreferenceNode(String name, String value, boolean readonly) {
this.name = name;
this.value = value;
this.readonly = readonly;
}
}

View File

@@ -1,43 +0,0 @@
package com.phonegap;
import java.util.HashSet;
import com.phonegap.PreferenceNode;
public class PreferenceSet {
private HashSet<PreferenceNode> innerSet;
public PreferenceSet() {
this.innerSet = new HashSet<PreferenceNode>();
}
public void add(PreferenceNode node) {
this.innerSet.add(node);
}
public int size() {
return this.innerSet.size();
}
public void clear() {
this.innerSet.clear();
}
public String pref(String prefName) {
for (PreferenceNode n : innerSet)
if (prefName.equals(n.name))
return n.value;
return null;
}
public boolean prefMatches(String prefName, String prefValue) {
String value = pref(prefName);
if (value == null) {
return false;
} else {
return value.equals(prefValue);
}
}
}

View File

@@ -18,99 +18,10 @@
*/
package com.phonegap.api;
import org.json.JSONArray;
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 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 a message is sent to plugin.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data);
/**
* 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 {
}

View File

@@ -18,217 +18,11 @@
*/
package com.phonegap.api;
import android.util.Log;
/**
* Log to Android logging system.
*
* Log message can be a string or a printf formatted string with arguments.
* See http://developer.android.com/reference/java/util/Formatter.html
*/
public class LOG {
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 {
}

View File

@@ -19,62 +19,10 @@
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 {
/**
* @deprecated
* Add services to res/xml/plugins.xml instead.
*
* Add a class that implements a service.
*
* @param serviceType
* @param className
*/
@Deprecated
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);
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
abstract public void postMessage(String id, Object data);
public abstract class PhonegapActivity extends Activity implements org.apache.cordova.api.CordovaInterface {
}

View File

@@ -18,193 +18,10 @@
*/
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 a message is sent to plugin.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data) {
}
/**
* 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 {
}

View File

@@ -18,342 +18,19 @@
*/
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);
// Create plugin at load time if attribute "onload"
if ("true".equals(xml.getAttributeValue(null, "onload"))) {
this.getPlugin(pluginName);
}
} 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);
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) {
for (IPlugin plugin : this.plugins.values()) {
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) {
for (IPlugin plugin : this.plugins.values()) {
plugin.onResume(multitasking);
}
}
/**
* The final call you receive before your activity is destroyed.
*/
public void onDestroy() {
for (IPlugin plugin : this.plugins.values()) {
plugin.onDestroy();
}
}
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
public void postMessage(String id, Object data) {
for (IPlugin plugin : this.plugins.values()) {
plugin.onMessage(id, data);
}
}
/**
* Called when the activity receives a new intent.
*/
public void onNewIntent(Intent intent) {
for (IPlugin plugin : this.plugins.values()) {
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("=====================================================================================");
}
}

View File

@@ -21,120 +21,33 @@ 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);
}
}

View File

@@ -16,17 +16,17 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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;
@@ -72,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);
}
@@ -148,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);
@@ -167,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;
}
}

View File

@@ -17,14 +17,14 @@
under the License.
*/
package com.phonegap;
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;
/**

View File

@@ -16,22 +16,23 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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;
import com.phonegap.api.LOG;
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):

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import android.media.AudioManager;
import android.media.MediaPlayer;
@@ -28,11 +28,12 @@ import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* This class implements the audio playback and recording capabilities used by 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:
@@ -116,7 +117,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+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
// Make sure we're not already recording
@@ -137,11 +138,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+", { \"code\":"+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+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
}
@@ -183,7 +184,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+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
// If this is a new request to play audio, or stopped
@@ -215,9 +216,16 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
android.content.res.AssetFileDescriptor fd = this.handler.ctx.getBaseContext().getAssets().openFd(f);
this.mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
}
else {
this.mPlayer.setDataSource("/sdcard/" + file);
}
else {
File fp = new File(file);
if (fp.exists()) {
FileInputStream fileInputStream = new FileInputStream(file);
this.mPlayer.setDataSource(fileInputStream.getFD());
}
else {
this.mPlayer.setDataSource("/sdcard/" + file);
}
}
this.setState(MEDIA_STARTING);
this.mPlayer.setOnPreparedListener(this);
this.mPlayer.prepare();
@@ -228,7 +236,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+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
}
@@ -242,7 +250,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+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
}
}
@@ -254,7 +262,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+");");
}
}
@@ -270,7 +278,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+", { \"code\":"+MEDIA_ERR_NONE_ACTIVE+"});");
}
}
@@ -284,7 +292,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+", { \"code\":"+MEDIA_ERR_NONE_ACTIVE+"});");
}
}
@@ -305,7 +313,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 {
@@ -384,7 +392,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+");");
}
@@ -413,7 +421,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 + "', { \"code\":"+arg1+"});");
return false;
}
@@ -424,7 +432,7 @@ 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;

View File

@@ -1,4 +1,22 @@
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;
/**
* The Class AuthenticationToken defines the userName and password to be used for authenticating a web resource

View File

@@ -16,14 +16,14 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.BufferedReader;
import java.io.DataOutputStream;
@@ -31,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.
*
@@ -107,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+")");
@@ -137,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();

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -26,19 +26,18 @@ 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;
@@ -108,16 +107,13 @@ public class CameraLauncher extends Plugin {
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);
this.mediaType = args.getInt(6);
if (srcType == CAMERA) {
this.takePicture(destType, encodingType);
@@ -143,7 +139,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:
@@ -179,9 +175,9 @@ 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), "Pic.png");
photo = new File(DirectoryManager.getTempDirectoryPath(ctx.getContext()), "Pic.png");
} else {
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
}
@@ -276,19 +272,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 {
@@ -379,6 +380,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();
@@ -398,11 +413,17 @@ 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;

View File

@@ -16,12 +16,15 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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;
@@ -35,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";
@@ -128,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);
}
}
@@ -167,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());
@@ -195,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);
@@ -235,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();
@@ -248,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
@@ -290,7 +291,7 @@ 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();
@@ -307,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);
@@ -318,7 +319,7 @@ 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 {
@@ -329,7 +330,7 @@ public class Capture extends Plugin {
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 {

View File

@@ -16,17 +16,17 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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;
@@ -59,6 +59,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
* Constructor.
*/
public CompassListener() {
this.heading = 0;
this.timeStamp = 0;
this.setStatus(CompassListener.STOPPED);
}
@@ -69,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);
}
@@ -99,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;
@@ -115,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));
@@ -127,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) {
@@ -147,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;
}
}
@@ -180,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();

View File

@@ -14,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;
@@ -36,7 +37,7 @@ import org.json.JSONObject;
public abstract class ContactAccessor {
protected final String LOG_TAG = "ContactsAccessor";
protected Activity mApp;
protected Context mApp;
protected WebView mView;
/**
@@ -83,7 +84,8 @@ public abstract class ContactAccessor {
map.put("displayName", true);
}
else if (key.startsWith("name")) {
map.put("name", true);
map.put("displayName", true);
map.put("name", true);
}
else if (key.startsWith("nickname")) {
map.put("nickname", true);

View File

@@ -1,20 +1,23 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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
package com.phonegap;
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.FileInputStream;
@@ -40,6 +43,7 @@ import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
@@ -118,8 +122,8 @@ public class ContactAccessorSdk5 extends ContactAccessor {
/**
* Create an contact accessor.
*/
public ContactAccessorSdk5(WebView view, Activity app) {
mApp = app;
public ContactAccessorSdk5(WebView view, Context context) {
mApp = context;
mView = view;
}
@@ -1614,9 +1618,20 @@ public class ContactAccessorSdk5 extends ContactAccessor {
* @param id the unique ID of the contact to remove
*/
public boolean remove(String id) {
int result = mApp.getContentResolver().delete(ContactsContract.Data.CONTENT_URI,
ContactsContract.Data.CONTACT_ID + " = ?",
new String[] {id});
int result = 0;
Cursor cursor = mApp.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null,
ContactsContract.Contacts._ID + " = ?",
new String[] {id}, null);
if(cursor.getCount() == 1) {
cursor.moveToFirst();
String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
result = mApp.getContentResolver().delete(uri, null, null);
} else {
Log.d(LOG_TAG, "Could not find contact with ID");
}
return (result > 0) ? true : false;
}
@@ -1634,71 +1649,73 @@ public class ContactAccessorSdk5 extends ContactAccessor {
*/
private int getPhoneType(String string) {
int type = ContactsContract.CommonDataKinds.Phone.TYPE_OTHER;
if ("home".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_HOME;
}
else if ("mobile".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
}
else if ("work".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_WORK;
}
else if ("work fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
}
else if ("home fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME;
}
else if ("fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
}
else if ("pager".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_PAGER;
}
else if ("other".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_OTHER;
}
else if ("car".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_CAR;
}
else if ("company main".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_COMPANY_MAIN;
}
else if ("isdn".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_ISDN;
}
else if ("main".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
}
else if ("other fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX;
}
else if ("radio".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_RADIO;
}
else if ("telex".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_TELEX;
}
else if ("work mobile".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE;
}
else if ("work pager".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER;
}
else if ("assistant".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_ASSISTANT;
}
else if ("mms".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_MMS;
}
else if ("callback".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_CALLBACK;
}
else if ("tty ttd".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_TTY_TDD;
}
else if ("custom".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM;
if (string != null) {
if ("home".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_HOME;
}
else if ("mobile".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
}
else if ("work".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_WORK;
}
else if ("work fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
}
else if ("home fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME;
}
else if ("fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
}
else if ("pager".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_PAGER;
}
else if ("other".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_OTHER;
}
else if ("car".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_CAR;
}
else if ("company main".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_COMPANY_MAIN;
}
else if ("isdn".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_ISDN;
}
else if ("main".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
}
else if ("other fax".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX;
}
else if ("radio".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_RADIO;
}
else if ("telex".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_TELEX;
}
else if ("work mobile".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE;
}
else if ("work pager".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER;
}
else if ("assistant".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_ASSISTANT;
}
else if ("mms".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_MMS;
}
else if ("callback".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_CALLBACK;
}
else if ("tty ttd".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_TTY_TDD;
}
else if ("custom".equals(string.toLowerCase())) {
return ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM;
}
}
return type;
}

View 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);
}
}
}

View File

@@ -16,11 +16,11 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import org.apache.cordova.api.LOG;
import org.json.JSONArray;
import org.json.JSONException;
import com.phonegap.api.LOG;
import android.app.AlertDialog;
import android.content.Context;
@@ -42,7 +42,7 @@ import android.widget.EditText;
public class CordovaChromeClient extends WebChromeClient {
private String TAG = "PhoneGapLog";
private String TAG = "CordovaLog";
private long MAX_QUOTA = 100 * 1024 * 1024;
private DroidGap ctx;
@@ -213,9 +213,12 @@ public class CordovaChromeClient extends WebChromeClient {
result.confirm(r);
}
// PhoneGap JS has initialized, so show webview
// Cordova JS has initialized, so show webview
// (This solves white flash seen when rendering HTML)
else if (reqOk && defaultValue != null && defaultValue.equals("gap_init:")) {
if (ctx.splashscreen != 0) {
ctx.root.setBackgroundResource(0);
}
ctx.appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
result.confirm("OK");

View File

@@ -16,9 +16,9 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import com.phonegap.api.LOG;
import org.apache.cordova.api.LOG;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -64,7 +64,7 @@ public class CordovaWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// First give any plugins the chance to handle the url themselves
if (this.ctx.pluginManager.onOverrideUrlLoading(url)) {
if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) {
}
// If dialing phone (tel:5551212)
@@ -135,7 +135,7 @@ public class CordovaWebViewClient extends WebViewClient {
// All else
else {
// If our app or file:, then load into a new phonegap webview container by starting a new instance of our activity.
// 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);
@@ -183,7 +183,6 @@ public class CordovaWebViewClient extends WebViewClient {
@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();
@@ -218,10 +217,11 @@ public class CordovaWebViewClient extends WebViewClient {
// 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{ PhoneGap.onNativeReady.fire();}catch(e){_nativeReady = true;}");
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 PhoneGap JS never initialized correctly
// 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() {
@@ -229,6 +229,9 @@ public class CordovaWebViewClient extends WebViewClient {
Thread.sleep(2000);
ctx.runOnUiThread(new Runnable() {
public void run() {
if (ctx.splashscreen != 0) {
ctx.root.setBackgroundResource(0);
}
ctx.appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
}
@@ -293,4 +296,15 @@ public class CordovaWebViewClient extends WebViewClient {
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);
}
}
}

View File

@@ -16,16 +16,17 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
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 com.phonegap.api.LOG;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -37,73 +38,73 @@ import android.telephony.TelephonyManager;
public class Device extends Plugin {
public static final String TAG = "Device";
public static String phonegapVersion = "1.4.1"; // PhoneGap version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
public static String cordovaVersion = "1.7.0rc1"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
BroadcastReceiver telephonyReceiver = null;
/**
* Constructor.
*/
public Device() {
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);
/**
* 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("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);
}
}
/**
* 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;
}
/**
* 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.
@@ -124,7 +125,7 @@ public class Device extends Plugin {
private void initTelephonyReceiver() {
IntentFilter intentFilter = new IntentFilter() ;
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
final PhonegapActivity myctx = this.ctx;
final CordovaInterface myctx = this.ctx;
this.telephonyReceiver = new BroadcastReceiver() {
@Override
@@ -155,59 +156,59 @@ public class Device extends Plugin {
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 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;
}
/**
* 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();

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.File;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.IOException;
import java.util.ArrayList;
@@ -27,26 +27,28 @@ import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONArray;
import org.json.JSONException;
import org.apache.cordova.PreferenceNode;
import org.apache.cordova.PreferenceSet;
import org.apache.cordova.api.IPlugin;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.PluginManager;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.database.Cursor;
import android.graphics.Color;
import android.media.AudioManager;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
@@ -55,40 +57,26 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ConsoleMessage;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.HttpAuthHandler;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.phonegap.api.IPlugin;
import com.phonegap.api.LOG;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.PluginManager;
import com.phonegap.PreferenceNode;
import com.phonegap.PreferenceSet;
/**
* This class is the main Android activity that represents the PhoneGap
* This class is the main Android activity that represents the Cordova
* application. It should be extended by the user to load the specific
* html file that contains the application.
*
* As an example:
*
* package com.phonegap.examples;
* package org.apache.cordova.examples;
* import android.app.Activity;
* import android.os.Bundle;
* import com.phonegap.*;
* import org.apache.cordova.*;
*
* public class Examples extends DroidGap {
* @Override
@@ -140,26 +128,26 @@ import com.phonegap.PreferenceSet;
* // Enable app to keep running in background. (Boolean - default=true)
* super.setBooleanProperty("keepRunning", false);
*
* Phonegap.xml configuration:
* PhoneGap uses a configuration file at res/xml/phonegap.xml to specify the following settings.
* Cordova.xml configuration:
* Cordova uses a configuration file at res/xml/cordova.xml to specify the following settings.
*
* Approved list of URLs that can be loaded into DroidGap
* <access origin="http://server regexp" subdomains="true" />
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
* <log level="DEBUG" />
*
* Phonegap plugins:
* PhoneGap uses a file at res/xml/plugins.xml to list all plugins that are installed.
* Cordova plugins:
* Cordova uses a file at res/xml/plugins.xml to list all plugins that are installed.
* Before using a new plugin, a new element must be added to the file.
* name attribute is the service name passed to PhoneGap.exec() in JavaScript
* name attribute is the service name passed to Cordova.exec() in JavaScript
* value attribute is the Java class name to call.
*
* <plugins>
* <plugin name="App" value="com.phonegap.App"/>
* <plugin name="App" value="org.apache.cordova.App"/>
* ...
* </plugins>
*/
public class DroidGap extends PhonegapActivity {
public class DroidGap extends Activity implements CordovaInterface {
public static String TAG = "DroidGap";
// The webview for our app
@@ -223,11 +211,9 @@ public class DroidGap extends PhonegapActivity {
// when another application (activity) is started.
protected boolean keepRunning = true;
// preferences read from phonegap.xml
// preferences read from cordova.xml
protected PreferenceSet preferences;
private boolean classicRender;
/**
* Sets the authentication token.
*
@@ -319,7 +305,7 @@ public class DroidGap extends PhonegapActivity {
public void onCreate(Bundle savedInstanceState) {
preferences = new PreferenceSet();
// Load PhoneGap configuration:
// Load Cordova configuration:
// white list of allowed URLs
// debug setting
this.loadConfiguration();
@@ -361,22 +347,33 @@ public class DroidGap extends PhonegapActivity {
}
/**
* Create and initialize web container.
* Create and initialize web container with default web view objects.
*/
public void init() {
this.init(new WebView(DroidGap.this), new CordovaWebViewClient(this), new CordovaChromeClient(DroidGap.this));
}
/**
* Initialize web container with web view objects.
*
* @param webView
* @param webViewClient
* @param webChromeClient
*/
public void init(WebView webView, WebViewClient webViewClient, WebChromeClient webChromeClient) {
LOG.d(TAG, "DroidGap.init()");
// Create web container
this.appView = new WebView(DroidGap.this);
// Set up web container
this.appView = webView;
this.appView.setId(100);
this.appView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT,
1.0F));
this.appView.setWebChromeClient(new CordovaChromeClient(DroidGap.this));
this.setWebViewClient(this.appView, new CordovaWebViewClient(this));
this.appView.setWebChromeClient(webChromeClient);
this.setWebViewClient(this.appView, webViewClient);
this.appView.setInitialScale(0);
this.appView.setVerticalScrollBarEnabled(false);
@@ -409,6 +406,9 @@ public class DroidGap extends PhonegapActivity {
// Clear cancel flag
this.cancelLoadUrl = false;
// Create plugin manager
this.pluginManager = new PluginManager(this.appView, this);
}
/**
@@ -514,12 +514,7 @@ public class DroidGap extends PhonegapActivity {
else {
me.callbackServer.reinit(url);
}
if (me.pluginManager == null) {
me.pluginManager = new PluginManager(me.appView, me);
}
else {
me.pluginManager.reinit();
}
me.pluginManager.init();
// If loadingDialog property, then show the App loading dialog for first page of app
String loading = null;
@@ -847,11 +842,13 @@ public class DroidGap extends PhonegapActivity {
}
// Send pause event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.fireDocumentEvent('pause');}catch(e){};");
this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onPause.fire();}catch(e){console.log('exception firing pause event from native');};");
// Forward to plugins
this.pluginManager.onPause(this.keepRunning);
if (this.pluginManager != null) {
this.pluginManager.onPause(this.keepRunning);
}
// If app doesn't want to run in background
if (!this.keepRunning) {
@@ -868,7 +865,9 @@ public class DroidGap extends PhonegapActivity {
super.onNewIntent(intent);
//Forward to plugins
this.pluginManager.onNewIntent(intent);
if (this.pluginManager != null) {
this.pluginManager.onNewIntent(intent);
}
}
@Override
@@ -888,11 +887,13 @@ public class DroidGap extends PhonegapActivity {
}
// Send resume event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.fireDocumentEvent('resume');}catch(e){};");
this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onResume.fire();}catch(e){console.log('exception firing resume event from native');};");
// Forward to plugins
this.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
if (this.pluginManager != null) {
this.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
}
// If app doesn't want to run in background
if (!this.keepRunning || this.activityResultKeepRunning) {
@@ -918,13 +919,15 @@ public class DroidGap extends PhonegapActivity {
// Send destroy event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.onDestroy.fire();}catch(e){};");
this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
// Load blank page so that JavaScript onunload is called
this.appView.loadUrl("about:blank");
// Forward to plugins
this.pluginManager.onDestroy();
if (this.pluginManager != null) {
this.pluginManager.onDestroy();
}
}
else {
this.endActivity();
@@ -940,7 +943,9 @@ public class DroidGap extends PhonegapActivity {
public void postMessage(String id, Object data) {
// Forward to plugins
this.pluginManager.postMessage(id, data);
if (this.pluginManager != null) {
this.pluginManager.postMessage(id, data);
}
}
/**
@@ -954,7 +959,9 @@ public class DroidGap extends PhonegapActivity {
*/
@Deprecated
public void addService(String serviceType, String className) {
this.pluginManager.addService(serviceType, className);
if (this.pluginManager != null) {
this.pluginManager.addService(serviceType, className);
}
}
/**
@@ -964,16 +971,18 @@ public class DroidGap extends PhonegapActivity {
* @param message
*/
public void sendJavascript(String statement) {
this.callbackServer.sendJavascript(statement);
//We need to check for the null case on the Kindle Fire beacuse it changes the width and height on load
if(this.callbackServer != null)
this.callbackServer.sendJavascript(statement);
}
/**
* Load the specified URL in the PhoneGap webview or a new browser instance.
* Load the specified URL in the Cordova webview or a new browser instance.
*
* NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
*
* @param url The url to load.
* @param openExternal Load url in browser instead of PhoneGap webview.
* @param openExternal Load url in browser instead of Cordova webview.
* @param clearHistory Clear the history stack, so new page becomes top of history
* @param params DroidGap parameters for new app
*/
@@ -1064,51 +1073,46 @@ public class DroidGap extends PhonegapActivity {
}
/**
* Called when a key is pressed.
* Called when a key is de-pressed. (Key UP)
*
* @param keyCode
* @param event
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (this.appView == null) {
return super.onKeyDown(keyCode, event);
return super.onKeyUp(keyCode, event);
}
// If back key
if (keyCode == KeyEvent.KEYCODE_BACK) {
// If back key is bound, then send event to JavaScript
if (this.bound) {
this.appView.loadUrl("javascript:PhoneGap.fireDocumentEvent('backbutton');");
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
return true;
}
// If not bound
else {
} else {
// If not bound
// Go to previous page in webview if it is possible to go back
if (this.backHistory()) {
return true;
}
// If not, then invoke behavior of super class
else {
this.activityState = ACTIVITY_EXITING;
return super.onKeyDown(keyCode, event);
return super.onKeyUp(keyCode, event);
}
}
}
// If menu key
else if (keyCode == KeyEvent.KEYCODE_MENU) {
this.appView.loadUrl("javascript:PhoneGap.fireDocumentEvent('menubutton');");
return super.onKeyDown(keyCode, event);
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
return super.onKeyUp(keyCode, event);
}
// If search key
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
this.appView.loadUrl("javascript:PhoneGap.fireDocumentEvent('searchbutton');");
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
return true;
}
@@ -1171,7 +1175,6 @@ public class DroidGap extends PhonegapActivity {
}
}
@Override
public void setActivityResultCallback(IPlugin plugin) {
this.activityResultCallback = plugin;
}
@@ -1198,13 +1201,16 @@ public class DroidGap extends PhonegapActivity {
}
});
}
// If not, then display error dialog
else {
final boolean exit = !(errorCode == WebViewClient.ERROR_HOST_LOOKUP);
me.runOnUiThread(new Runnable() {
public void run() {
me.appView.setVisibility(View.GONE);
me.displayError("Application Error", description + " ("+failingUrl+")", "OK", true);
if(exit)
{
me.appView.setVisibility(View.GONE);
me.displayError("Application Error", description + " ("+failingUrl+")", "OK", exit);
}
}
});
}
@@ -1243,16 +1249,16 @@ public class DroidGap extends PhonegapActivity {
/**
* Load PhoneGap configuration from res/xml/phonegap.xml.
* Load Cordova configuration from res/xml/cordova.xml.
* Approved list of URLs that can be loaded into DroidGap
* <access origin="http://server regexp" subdomains="true" />
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
* <log level="DEBUG" />
*/
private void loadConfiguration() {
int id = getResources().getIdentifier("phonegap", "xml", getPackageName());
int id = getResources().getIdentifier("cordova", "xml", getPackageName());
if (id == 0) {
LOG.i("PhoneGapLog", "phonegap.xml missing. Ignoring...");
LOG.i("CordovaLog", "cordova.xml missing. Ignoring...");
return;
}
XmlResourceParser xml = getResources().getXml(id);
@@ -1269,7 +1275,7 @@ public class DroidGap extends PhonegapActivity {
}
else if (strNode.equals("log")) {
String level = xml.getAttributeValue(null, "level");
LOG.i("PhoneGapLog", "Found log level %s", level);
LOG.i("CordovaLog", "Found log level %s", level);
if (level != null) {
LOG.setLogLevel(level);
}
@@ -1282,7 +1288,7 @@ public class DroidGap extends PhonegapActivity {
boolean readonly = (readonlyString != null &&
readonlyString.equals("true"));
LOG.i("PhoneGapLog", "Found preference for %s", name);
LOG.i("CordovaLog", "Found preference for %s", name);
preferences.add(new PreferenceNode(name, value, readonly));
}
@@ -1341,7 +1347,7 @@ public class DroidGap extends PhonegapActivity {
* @param url
* @return
*/
boolean isUrlWhiteListed(String url) {
public boolean isUrlWhiteListed(String url) {
// Check to see if we have matched url previously
if (whiteListCache.get(url) != null) {
@@ -1362,7 +1368,31 @@ public class DroidGap extends PhonegapActivity {
}
return false;
}
/*
* URL stack manipulators
*/
/**
* Returns the top url on the stack without removing it from
* the stack.
*/
public String peekAtUrlStack() {
if (urls.size() > 0) {
return urls.peek();
}
return "";
}
/**
* Add a url to the stack
*
* @param url
*/
public void pushUrl(String url) {
urls.push(url);
}
/*
* Hook in DroidGap for menu plugins
*
@@ -1388,4 +1418,19 @@ public class DroidGap extends PhonegapActivity {
this.postMessage("onOptionsItemSelected", item);
return true;
}
public Context getContext() {
return this;
}
public void bindBackButton(boolean override) {
// TODO Auto-generated method stub
this.bound = override;
}
public boolean isBackButtonBound() {
// TODO Auto-generated method stub
return this.bound;
}
}

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.IOException;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -41,6 +41,8 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -49,8 +51,6 @@ 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 {
@@ -67,7 +67,7 @@ public class FileTransfer extends Plugin {
private HostnameVerifier defaultHostnameVerifier = null;
/* (non-Javadoc)
* @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
* @see org.apache.cordova.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
*/
@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
@@ -94,14 +94,14 @@ public class FileTransfer extends Plugin {
mimeType = getArgument(args, 4, "image/jpeg");
JSONObject params = args.optJSONObject(5);
boolean trustEveryone = args.optBoolean(6);
boolean chunkedMode = args.optBoolean(7);
boolean chunkedMode = args.optBoolean(7) || args.isNull(7); //Always use chunked mode unless set to false as per API
FileUploadResult r = upload(source, target, 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 if (action.equals("download")) {
JSONObject r = download(source, target);
Log.d(LOG_TAG, "****** About to return a result from download");
return new PluginResult(PluginResult.Status.OK, r, "window.localFileSystem._castEntry");
return new PluginResult(PluginResult.Status.OK, r);
} else {
return new PluginResult(PluginResult.Status.INVALID_ACTION);
}
@@ -225,7 +225,7 @@ public class FileTransfer extends Plugin {
FileUploadResult result = new FileUploadResult();
// Get a input stream of the file on the phone
InputStream fileInputStream = getPathFromUri(file);
FileInputStream fileInputStream = (FileInputStream) getPathFromUri(file);
HttpURLConnection conn = null;
DataOutputStream dos = null;
@@ -277,37 +277,71 @@ public class FileTransfer extends Plugin {
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY);
// Handle the other headers
try {
JSONObject headers = params.getJSONObject("headers");
for (Iterator iter = headers.keys(); iter.hasNext();)
{
String headerKey = iter.next().toString();
conn.setRequestProperty(headerKey, headers.getString(headerKey));
}
} catch (JSONException e1) {
// No headers to be manipulated!
}
// 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
/*
* Store the non-file portions of the multipart data as a string, so that we can add it
* to the contentSize, since it is part of the body of the HTTP request.
*/
String extraParams = "";
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);
if(key.toString() != "headers")
{
extraParams += LINE_START + BOUNDRY + LINE_END;
extraParams += "Content-Disposition: form-data; name=\"" + key.toString() + "\";";
extraParams += LINE_END + LINE_END;
extraParams += params.getString(key.toString());
extraParams += LINE_END;
}
}
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
extraParams += LINE_START + BOUNDRY + LINE_END;
extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"";
String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END;
String tailParams = LINE_END + LINE_START + BOUNDRY + LINE_START + LINE_END;
// Should set this up as an option
if (chunkedMode) {
conn.setChunkedStreamingMode(maxBufferSize);
}
else
{
int stringLength = extraParams.length() + midParams.length() + tailParams.length() + fileName.getBytes("UTF-8").length;
Log.d(LOG_TAG, "String Length: " + stringLength);
int fixedLength = (int) fileInputStream.getChannel().size() + stringLength;
Log.d(LOG_TAG, "Content Length: " + fixedLength);
conn.setFixedLengthStreamingMode(fixedLength);
}
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);
dos = new DataOutputStream( conn.getOutputStream() );
dos.writeBytes(extraParams);
//We don't want to chagne encoding, we just want this to write for all Unicode.
dos.write(fileName.getBytes("UTF-8"));
dos.writeBytes(midParams);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
@@ -328,8 +362,7 @@ public class FileTransfer extends Plugin {
}
// send multipart form data necesssary after file data...
dos.writeBytes(LINE_END);
dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END);
dos.writeBytes(tailParams);
// close streams
fileInputStream.close();
@@ -377,38 +410,53 @@ public class FileTransfer extends Plugin {
*/
public JSONObject download(String source, String target) throws IOException {
try {
File file = new File(target);
File file = getFileFromPath(target);
// create needed directories
file.getParentFile().mkdirs();
// connect to server
URL url = new URL(source);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
if(this.ctx.isUrlWhiteListed(source))
{
URL url = new URL(source);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
//Add cookie support
String cookie = CookieManager.getInstance().getCookie(source);
if(cookie != null)
{
connection.setRequestProperty("cookie", cookie);
}
connection.connect();
Log.d(LOG_TAG, "Download file:" + url);
Log.d(LOG_TAG, "Download file:" + url);
InputStream inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;
InputStream inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;
FileOutputStream outputStream = new FileOutputStream(file);
FileOutputStream outputStream = new FileOutputStream(file);
// write bytes to file
while ( (bytesRead = inputStream.read(buffer)) > 0 ) {
// write bytes to file
while ( (bytesRead = inputStream.read(buffer)) > 0 ) {
outputStream.write(buffer,0, bytesRead);
}
outputStream.close();
Log.d(LOG_TAG, "Saved file: " + target);
// create FileEntry object
FileUtils fileUtil = new FileUtils();
return fileUtil.getEntry(file);
}
else
{
throw new IOException("Error: Unable to connect to domain");
}
outputStream.close();
Log.d(LOG_TAG, "Saved file: " + target);
// create FileEntry object
FileUtils fileUtil = new FileUtils();
return fileUtil.getEntry(file);
} catch (Exception e) {
Log.d(LOG_TAG, e.getMessage(), e);
throw new IOException("Error while downloading");
@@ -440,4 +488,17 @@ public class FileTransfer extends Plugin {
}
}
/**
* Get a File object from the passed in path
*
* @param path
* @return
*/
private File getFileFromPath(String path) {
if (path.startsWith("file://")) {
return new File(path.substring(7));
} else {
return new File(path);
}
}
}

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import org.json.JSONException;
import org.json.JSONObject;

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.*;
import java.net.MalformedURLException;
@@ -25,6 +25,14 @@ import java.net.URLDecoder;
import java.nio.channels.FileChannel;
import org.apache.commons.codec.binary.Base64;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.file.EncodingException;
import org.apache.cordova.file.FileExistsException;
import org.apache.cordova.file.InvalidModificationException;
import org.apache.cordova.file.NoModificationAllowedException;
import org.apache.cordova.file.TypeMismatchException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -36,14 +44,6 @@ import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import com.phonegap.file.EncodingException;
import com.phonegap.file.FileExistsException;
import com.phonegap.file.InvalidModificationException;
import com.phonegap.file.NoModificationAllowedException;
import com.phonegap.file.TypeMismatchException;
/**
* This class provides SD card file and directory services to JavaScript.
@@ -95,140 +95,122 @@ public class FileUtils extends Plugin {
//System.out.println("FileUtils.execute("+action+")");
try {
try {
if (action.equals("testSaveLocationExists")) {
boolean b = DirectoryManager.testSaveLocationExists();
return new PluginResult(status, b);
}
else if (action.equals("getFreeDiskSpace")) {
long l = DirectoryManager.getFreeDiskSpace(false);
return new PluginResult(status, l);
}
else if (action.equals("testFileExists")) {
boolean b = DirectoryManager.testFileExists(args.getString(0));
return new PluginResult(status, b);
}
else if (action.equals("testDirectoryExists")) {
boolean b = DirectoryManager.testFileExists(args.getString(0));
return new PluginResult(status, b);
}
else if (action.equals("readAsText")) {
String s = this.readAsText(args.getString(0), args.getString(1));
return new PluginResult(status, s);
}
else if (action.equals("readAsDataURL")) {
String s = this.readAsDataURL(args.getString(0));
return new PluginResult(status, s);
}
else if (action.equals("write")) {
long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2));
return new PluginResult(status, fileSize);
}
else if (action.equals("truncate")) {
long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
return new PluginResult(status, fileSize);
}
else if (action.equals("requestFileSystem")) {
long size = args.optLong(1);
if (size != 0) {
if (size > (DirectoryManager.getFreeDiskSpace(true)*1024)) {
JSONObject error = new JSONObject().put("code", FileUtils.QUOTA_EXCEEDED_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
}
}
JSONObject obj = requestFileSystem(args.getInt(0));
return new PluginResult(status, obj, "window.localFileSystem._castFS");
}
else if (action.equals("resolveLocalFileSystemURI")) {
JSONObject obj = resolveLocalFileSystemURI(args.getString(0));
return new PluginResult(status, obj, "window.localFileSystem._castEntry");
}
else if (action.equals("getMetadata")) {
JSONObject obj = getMetadata(args.getString(0));
return new PluginResult(status, obj, "window.localFileSystem._castDate");
}
else if (action.equals("getFileMetadata")) {
JSONObject obj = getFileMetadata(args.getString(0));
return new PluginResult(status, obj, "window.localFileSystem._castDate");
}
else if (action.equals("getParent")) {
JSONObject obj = getParent(args.getString(0));
return new PluginResult(status, obj, "window.localFileSystem._castEntry");
}
else if (action.equals("getDirectory")) {
JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), true);
return new PluginResult(status, obj, "window.localFileSystem._castEntry");
}
else if (action.equals("getFile")) {
JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), false);
return new PluginResult(status, obj, "window.localFileSystem._castEntry");
}
else if (action.equals("remove")) {
boolean success;
success = remove(args.getString(0));
if (success) {
notifyDelete(args.getString(0));
return new PluginResult(status);
} else {
JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
}
}
else if (action.equals("removeRecursively")) {
boolean success = removeRecursively(args.getString(0));
if (success) {
return new PluginResult(status);
} else {
JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
}
}
else if (action.equals("moveTo")) {
JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), true);
return new PluginResult(status, entry, "window.localFileSystem._castEntry");
}
else if (action.equals("copyTo")) {
JSONObject entry = transferTo(args.getString(0), args.getJSONObject(1), args.optString(2), false);
return new PluginResult(status, entry, "window.localFileSystem._castEntry");
}
else if (action.equals("readEntries")) {
JSONArray entries = readEntries(args.getString(0));
return new PluginResult(status, entries, "window.localFileSystem._castEntries");
}
return new PluginResult(status, result);
} catch (FileNotFoundException e) {
JSONObject error = new JSONObject().put("code", FileUtils.NOT_FOUND_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (FileExistsException e) {
JSONObject error = new JSONObject().put("code", FileUtils.PATH_EXISTS_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (NoModificationAllowedException e) {
JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (JSONException e) {
JSONObject error = new JSONObject().put("code", FileUtils.NO_MODIFICATION_ALLOWED_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (InvalidModificationException e) {
JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (MalformedURLException e) {
JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (IOException e) {
JSONObject error = new JSONObject().put("code", FileUtils.INVALID_MODIFICATION_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (EncodingException e) {
JSONObject error = new JSONObject().put("code", FileUtils.ENCODING_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
} catch (TypeMismatchException e) {
JSONObject error = new JSONObject().put("code", FileUtils.TYPE_MISMATCH_ERR);
return new PluginResult(PluginResult.Status.ERROR, error);
if (action.equals("testSaveLocationExists")) {
boolean b = DirectoryManager.testSaveLocationExists();
return new PluginResult(status, b);
}
else if (action.equals("getFreeDiskSpace")) {
long l = DirectoryManager.getFreeDiskSpace(false);
return new PluginResult(status, l);
}
else if (action.equals("testFileExists")) {
boolean b = DirectoryManager.testFileExists(args.getString(0));
return new PluginResult(status, b);
}
else if (action.equals("testDirectoryExists")) {
boolean b = DirectoryManager.testFileExists(args.getString(0));
return new PluginResult(status, b);
}
else if (action.equals("readAsText")) {
String s = this.readAsText(args.getString(0), args.getString(1));
return new PluginResult(status, s);
}
else if (action.equals("readAsDataURL")) {
String s = this.readAsDataURL(args.getString(0));
return new PluginResult(status, s);
}
else if (action.equals("write")) {
long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2));
return new PluginResult(status, fileSize);
}
else if (action.equals("truncate")) {
long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
return new PluginResult(status, fileSize);
}
else if (action.equals("requestFileSystem")) {
long size = args.optLong(1);
if (size != 0) {
if (size > (DirectoryManager.getFreeDiskSpace(true)*1024)) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR);
}
}
JSONObject obj = requestFileSystem(args.getInt(0));
return new PluginResult(status, obj);
}
else if (action.equals("resolveLocalFileSystemURI")) {
JSONObject obj = resolveLocalFileSystemURI(args.getString(0));
return new PluginResult(status, obj);
}
else if (action.equals("getMetadata")) {
return new PluginResult(status, getMetadata(args.getString(0)));
}
else if (action.equals("getFileMetadata")) {
JSONObject obj = getFileMetadata(args.getString(0));
return new PluginResult(status, obj);
}
else if (action.equals("getParent")) {
JSONObject obj = getParent(args.getString(0));
return new PluginResult(status, obj);
}
else if (action.equals("getDirectory")) {
JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), true);
return new PluginResult(status, obj);
}
else if (action.equals("getFile")) {
JSONObject obj = getFile(args.getString(0), args.getString(1), args.optJSONObject(2), false);
return new PluginResult(status, obj);
}
else if (action.equals("remove")) {
boolean success;
success = remove(args.getString(0));
if (success) {
notifyDelete(args.getString(0));
return new PluginResult(status);
} else {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NO_MODIFICATION_ALLOWED_ERR);
}
}
else if (action.equals("removeRecursively")) {
boolean success = removeRecursively(args.getString(0));
if (success) {
return new PluginResult(status);
} else {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NO_MODIFICATION_ALLOWED_ERR);
}
}
else if (action.equals("moveTo")) {
JSONObject entry = transferTo(args.getString(0), args.getString(1), args.getString(2), true);
return new PluginResult(status, entry);
}
else if (action.equals("copyTo")) {
JSONObject entry = transferTo(args.getString(0), args.getString(1), args.getString(2), false);
return new PluginResult(status, entry);
}
else if (action.equals("readEntries")) {
JSONArray entries = readEntries(args.getString(0));
return new PluginResult(status, entries);
}
return new PluginResult(status, result);
} catch (FileNotFoundException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR);
} catch (FileExistsException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.PATH_EXISTS_ERR);
} catch (NoModificationAllowedException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NO_MODIFICATION_ALLOWED_ERR);
} catch (JSONException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NO_MODIFICATION_ALLOWED_ERR);
} catch (InvalidModificationException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.INVALID_MODIFICATION_ERR);
} catch (MalformedURLException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.ENCODING_ERR);
} catch (IOException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.INVALID_MODIFICATION_ERR);
} catch (EncodingException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.ENCODING_ERR);
} catch (TypeMismatchException e) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.TYPE_MISMATCH_ERR);
}
}
@@ -271,7 +253,12 @@ public class FileUtils extends Plugin {
URL testUrl = new URL(decoded);
if (decoded.startsWith("file://")) {
fp = new File(decoded.substring(7, decoded.length()));
int questionMark = decoded.indexOf("?");
if (questionMark < 0) {
fp = new File(decoded.substring(7, decoded.length()));
} else {
fp = new File(decoded.substring(7, questionMark));
}
} else {
fp = new File(decoded);
}
@@ -295,7 +282,7 @@ public class FileUtils extends Plugin {
* @throws JSONException
*/
private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException {
File fp = new File(fileName);
File fp = createFileObject(fileName);
if (!fp.exists()) {
// The directory we are listing doesn't exist so we should fail.
@@ -328,7 +315,11 @@ public class FileUtils extends Plugin {
* @throws EncodingException
* @throws JSONException
*/
private JSONObject transferTo(String fileName, JSONObject newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException {
private JSONObject transferTo(String fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException {
fileName = stripFileProtocol(fileName);
newParent = stripFileProtocol(newParent);
// Check for invalid file name
if (newName != null && newName.contains(":")) {
throw new EncodingException("Bad file name");
@@ -341,7 +332,7 @@ public class FileUtils extends Plugin {
throw new FileNotFoundException("The source does not exist");
}
File destinationDir = new File(newParent.getString("fullPath"));
File destinationDir = new File(newParent);
if (!destinationDir.exists()) {
// The destination does not exist so we should fail.
throw new FileNotFoundException("The source does not exist");
@@ -569,7 +560,7 @@ public class FileUtils extends Plugin {
* @throws FileExistsException
*/
private boolean removeRecursively(String filePath) throws FileExistsException {
File fp = new File(filePath);
File fp = createFileObject(filePath);
// You can't delete the root directory.
if (atRootDirectory(filePath)) {
@@ -610,7 +601,7 @@ public class FileUtils extends Plugin {
* @throws InvalidModificationException
*/
private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException {
File fp = new File(filePath);
File fp = createFileObject(filePath);
// You can't delete the root directory.
if (atRootDirectory(filePath)) {
@@ -701,6 +692,7 @@ public class FileUtils extends Plugin {
if (fileName.startsWith("/")) {
fp = new File(fileName);
} else {
dirPath = stripFileProtocol(dirPath);
fp = new File(dirPath + File.separator + fileName);
}
return fp;
@@ -715,6 +707,8 @@ public class FileUtils extends Plugin {
* @throws JSONException
*/
private JSONObject getParent(String filePath) throws JSONException {
filePath = stripFileProtocol(filePath);
if (atRootDirectory(filePath)) {
return getEntry(filePath);
}
@@ -729,32 +723,57 @@ public class FileUtils extends Plugin {
* @return true if we are at the root, false otherwise.
*/
private boolean atRootDirectory(String filePath) {
filePath = stripFileProtocol(filePath);
if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getPackageName() + "/cache") ||
filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) ||
filePath.equals("/data/data/" + ctx.getPackageName())) {
return true;
}
return false;
}
/**
* This method removes the "file://" from the passed in filePath
*
* @param filePath to be checked.
* @return
*/
private String stripFileProtocol(String filePath) {
if (filePath.startsWith("file://")) {
filePath = filePath.substring(7);
}
return filePath;
}
/**
* Create a File object from the passed in path
*
* @param filePath
* @return
*/
private File createFileObject(String filePath) {
filePath = stripFileProtocol(filePath);
File file = new File(filePath);
return file;
}
/**
* Look up metadata about this entry.
*
* @param filePath to entry
* @return a Metadata object
* @return a long
* @throws FileNotFoundException
* @throws JSONException
*/
private JSONObject getMetadata(String filePath) throws FileNotFoundException, JSONException {
File file = new File(filePath);
private long getMetadata(String filePath) throws FileNotFoundException {
File file = createFileObject(filePath);
if (!file.exists()) {
throw new FileNotFoundException("Failed to find file in getMetadata");
}
JSONObject metadata = new JSONObject();
metadata.put("modificationTime", file.lastModified());
return metadata;
return file.lastModified();
}
/**
@@ -766,7 +785,7 @@ public class FileUtils extends Plugin {
* @throws JSONException
*/
private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException {
File file = new File(filePath);
File file = createFileObject(filePath);
if (!file.exists()) {
throw new FileNotFoundException("File: " + filePath + " does not exist.");
@@ -796,18 +815,18 @@ public class FileUtils extends Plugin {
File fp;
fs.put("name", "temporary");
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/"));
// Create the cache dir if it doesn't exist.
fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
} else {
fs.put("root", getEntry("/data/data/" + ctx.getPackageName() + "/cache/"));
// Create the cache dir if it doesn't exist.
fp.mkdirs();
fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/"));
} else {
fp = new File("/data/data/" + ctx.getPackageName() + "/cache/");
// Create the cache dir if it doesn't exist.
fp.mkdirs();
fs.put("root", getEntry("/data/data/" + ctx.getPackageName() + "/cache/"));
}
fp.mkdirs();
}
else if (type == PERSISTENT) {
fs.put("name", "persistent");
@@ -820,7 +839,7 @@ public class FileUtils extends Plugin {
else {
throw new IOException("No filesystem of type requested");
}
return fs;
}
@@ -837,7 +856,7 @@ public class FileUtils extends Plugin {
entry.put("isFile", file.isFile());
entry.put("isDirectory", file.isDirectory());
entry.put("name", file.getName());
entry.put("fullPath", file.getAbsolutePath());
entry.put("fullPath", "file://" + file.getAbsolutePath());
// I can't add the next thing it as it would be an infinite loop
//entry.put("filesystem", null);
@@ -892,8 +911,8 @@ public class FileUtils extends Plugin {
*/
public String readAsText(String filename, String encoding) throws FileNotFoundException, IOException {
byte[] bytes = new byte[1000];
BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int numRead = 0;
while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
bos.write(bytes, 0, numRead);
@@ -910,8 +929,8 @@ public class FileUtils extends Plugin {
*/
public String readAsDataURL(String filename) throws FileNotFoundException, IOException {
byte[] bytes = new byte[1000];
BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int numRead = 0;
while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
bos.write(bytes, 0, numRead);
@@ -953,22 +972,24 @@ public class FileUtils extends Plugin {
*/
/**/
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException {
filename = stripFileProtocol(filename);
boolean append = false;
if (offset > 0) {
this.truncateFile(filename, offset);
append = true;
}
byte [] rawData = data.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(rawData);
FileOutputStream out = new FileOutputStream(filename, append);
byte buff[] = new byte[rawData.length];
in.read(buff, 0, buff.length);
out.write(buff, 0, rawData.length);
out.flush();
out.close();
byte [] rawData = data.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(rawData);
FileOutputStream out = new FileOutputStream(filename, append);
byte buff[] = new byte[rawData.length];
in.read(buff, 0, buff.length);
out.write(buff, 0, rawData.length);
out.flush();
out.close();
return data.length();
return rawData.length;
}
/**
@@ -979,6 +1000,8 @@ public class FileUtils extends Plugin {
* @throws FileNotFoundException, IOException
*/
private long truncateFile(String filename, long size) throws FileNotFoundException, IOException {
filename = stripFileProtocol(filename);
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
if (raf.length() >= size) {
@@ -1003,6 +1026,7 @@ public class FileUtils extends Plugin {
return ctx.getContentResolver().openInputStream(uri);
}
else {
path = stripFileProtocol(path);
return new FileInputStream(path);
}
}
@@ -1014,7 +1038,7 @@ public class FileUtils extends Plugin {
* @param ctx the current applicaiton context
* @return the full path to the file
*/
protected static String getRealPathFromURI(Uri contentUri, PhonegapActivity ctx) {
protected static String getRealPathFromURI(Uri contentUri, CordovaInterface ctx) {
String[] proj = { _DATA };
Cursor cursor = ctx.managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA);

View File

@@ -16,16 +16,16 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.util.HashMap;
import java.util.Map.Entry;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
/*
* This class is the interface to the Geolocation. It's bound to the geo object.

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import android.content.Context;
import android.location.Location;

View File

@@ -17,9 +17,9 @@
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import com.phonegap.api.PhonegapActivity;
import org.apache.cordova.api.CordovaInterface;
import android.content.Context;
import android.location.Location;
@@ -33,7 +33,7 @@ import android.os.Bundle;
*/
public class GpsListener implements LocationListener {
private PhonegapActivity mCtx; // PhonegapActivity object
private CordovaInterface mCtx; // CordovaActivity object
private LocationManager mLocMan; // Location manager object
private GeoListener owner; // Geolistener object (parent)
@@ -49,7 +49,7 @@ public class GpsListener implements LocationListener {
* @param interval
* @param m
*/
public GpsListener(PhonegapActivity ctx, int interval, GeoListener m) {
public GpsListener(CordovaInterface ctx, int interval, GeoListener m) {
this.owner = m;
this.mCtx = ctx;
this.mLocMan = (LocationManager) this.mCtx.getSystemService(Context.LOCATION_SERVICE);

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import java.io.FileOutputStream;
import java.io.IOException;

View File

@@ -16,8 +16,8 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
import com.phonegap.api.LOG;
package org.apache.cordova;
import org.apache.cordova.api.LOG;
import android.content.Context;
import android.view.View.MeasureSpec;
@@ -87,13 +87,13 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
// gone away.
else if (height > oldHeight) {
if(app != null)
app.sendJavascript("PhoneGap.fireDocumentEvent('hidekeyboard');");
app.sendJavascript("cordova.fireDocumentEvent('hidekeyboard');");
}
// If the height as gotten smaller then we will assume the soft keyboard has
// been displayed.
else if (height < oldHeight) {
if(app != null)
app.sendJavascript("PhoneGap.fireDocumentEvent('showkeyboard');");
app.sendJavascript("cordova.fireDocumentEvent('showkeyboard');");
}
// Update the old height for the next event

View File

@@ -16,9 +16,9 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import com.phonegap.api.PhonegapActivity;
import org.apache.cordova.api.CordovaInterface;
import android.content.Context;
import android.location.Location;
@@ -28,13 +28,13 @@ import android.os.Bundle;
public class NetworkListener implements LocationListener {
private PhonegapActivity mCtx; // PhonegapActivity object
private CordovaInterface mCtx; // CordovaActivity object
private LocationManager mLocMan; // Location manager object
private GeoListener owner; // Geolistener object (parent)
private boolean hasData = false; // Flag indicates if location data is available in cLoc
private Location cLoc; // Last recieved location
private boolean running = false; // Flag indicates if listener is running
private LocationManager mLocMan; // Location manager object
private GeoListener owner; // Geolistener object (parent)
private boolean hasData = false; // Flag indicates if location data is available in cLoc
private Location cLoc; // Last recieved location
private boolean running = false; // Flag indicates if listener is running
/**
* Constructor.
@@ -44,7 +44,7 @@ public class NetworkListener implements LocationListener {
* @param interval
* @param m
*/
public NetworkListener(PhonegapActivity ctx, int interval, GeoListener m) {
public NetworkListener(CordovaInterface ctx, int interval, GeoListener m) {
this.owner = m;
this.mCtx = ctx;
this.mLocMan = (LocationManager) this.mCtx.getSystemService(Context.LOCATION_SERVICE);
@@ -115,7 +115,7 @@ public class NetworkListener implements LocationListener {
this.hasData = true;
this.cLoc = location;
// The GPS is the primary form of Geolocation in PhoneGap.
// The GPS is the primary form of Geolocation in Cordova.
// Only fire the success variables if the GPS is down for some reason.
if (!this.owner.mGps.hasLocation()) {
this.owner.success(location);

View File

@@ -16,13 +16,13 @@
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
package org.apache.cordova;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -58,7 +58,7 @@ public class NetworkManager extends Plugin {
public static final String LTE = "lte";
public static final String UMB = "umb";
public static final String HSPA_PLUS = "hspa+";
// return types
// return type
public static final String TYPE_UNKNOWN = "unknown";
public static final String TYPE_ETHERNET = "ethernet";
public static final String TYPE_WIFI = "wifi";
@@ -87,9 +87,9 @@ public class NetworkManager extends Plugin {
*
* @param ctx The context of the main Activity.
*/
public void setContext(PhonegapActivity ctx) {
public void setContext(CordovaInterface ctx) {
super.setContext(ctx);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
this.connectionCallbackId = null;
// We need to listen to connectivity events to update navigator.connection
@@ -98,7 +98,7 @@ public class NetworkManager extends Plugin {
if (this.receiver == null) {
this.receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
public void onReceive(Context context, Intent intent) {
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
}
};
@@ -117,7 +117,7 @@ public class NetworkManager extends Plugin {
*/
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.INVALID_ACTION;
String result = "Unsupported Operation: " + action;
String result = "Unsupported Operation: " + action;
if (action.equals("getConnectionInfo")) {
this.connectionCallbackId = callbackId;
@@ -137,8 +137,7 @@ public class NetworkManager extends Plugin {
* @return T=returns value
*/
public boolean isSynch(String action) {
// All methods take a while, so always use async
return false;
return true;
}
/**
@@ -182,7 +181,7 @@ public class NetworkManager extends Plugin {
// If we are not connected to any network set type to none
if (!info.isConnected()) {
type = TYPE_NONE;
}
}
else {
type = getType(info);
}
@@ -212,7 +211,7 @@ public class NetworkManager extends Plugin {
*/
private String getType(NetworkInfo info) {
if (info != null) {
String type = info.getTypeName();
String type = info.getTypeName();
if (type.toLowerCase().equals(WIFI)) {
return TYPE_WIFI;

View File

@@ -0,0 +1,366 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
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.getContext(), 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 CordovaInterface ctx = this.ctx;
final Notification notification = this;
Runnable runnable = new Runnable() {
public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getContext());
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 CordovaInterface 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.getContext());
dlg.setMessage(message);
dlg.setTitle(title);
dlg.setCancelable(false);
// First button
if (fButtons.length > 0) {
dlg.setNegativeButton(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.setPositiveButton(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 CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.spinnerDialog = ProgressDialog.show(ctx.getContext(), 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 CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.progressDialog = new ProgressDialog(ctx.getContext());
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;
}
}
}

View File

@@ -0,0 +1,34 @@
/*
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;
// represents the <preference> element from the W3C config.xml spec
// see http://www.w3.org/TR/widgets/#the-preference-element-and-its-attributes
public class PreferenceNode {
public String name;
public String value;
public boolean readonly;
// constructor
public PreferenceNode(String name, String value, boolean readonly) {
this.name = name;
this.value = value;
this.readonly = readonly;
}
}

Some files were not shown because too many files have changed in this diff Show More