Compare commits

...

188 Commits
1.3.0 ... 1.6.0

Author SHA1 Message Date
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
macdonst
3bff8aec88 Tagging 1.4.1 2012-02-01 15:35:57 -05:00
macdonst
e64cb2fc4f Removing deprecated methods from Device
Device.overrideBackButton
Device.exitApp
Device.resetBackButton
2012-02-01 10:46:27 -05:00
macdonst
c5ada0f09f Deprecating navigator.app.overrideBackbutton
Everyone should be using:

    document.addEventListener("backbutton", yourCallbackFunction, false);
2012-01-31 15:02:11 -05:00
macdonst
44edcbb3cf Updating version to 1.4.0 2012-01-30 16:07:20 -05:00
macdonst
3fd2f590fd Updating version to 1.4.0rc1 2012-01-27 12:06:26 -05:00
macdonst
4f61531422 Fixing a timing issue with the web view history not being cleared properly 2012-01-27 12:02:31 -05:00
macdonst
6e82ec4152 Allow internal SD Card to be used as storage 2012-01-25 16:34:46 -05:00
Joe Bowser
9206dca741 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-25 11:41:24 -08:00
Joe Bowser
503640f6b5 Removing the classic render feature, since it's not working properly 2012-01-25 11:40:46 -08:00
Bryce Curtis
e1e04f859c Remove unused files/classes until they are needed. 2012-01-24 22:42:41 -06:00
Bryce Curtis
e30896155c Added license header to new files. 2012-01-24 22:35:16 -06:00
Bryce Curtis
282f59cd99 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-24 15:03:40 -06:00
macdonst
89e260a5a1 CB-199: FileTransfer.download fails on Android 4.0
The download method in FileTransfer was setting the HttpURLConnection.setDoOutput to true. On Android 4.0 this would force the connection to be a POST when what we actually want is a GET.

I removed the offending line and tested the fix in 2.1, 2.2, 2.3 and 4.0.
2012-01-24 11:24:06 -05:00
Bryce Curtis
20891aee1a Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-23 21:10:40 -06:00
macdonst
6e5ef1e819 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-23 20:15:51 -05:00
Anis Kadri
e8544d30d1 Merge branch 'master' of github.com:imhotep/incubator-cordova-android 2012-01-23 16:21:11 -08:00
Bryce Curtis
f9af33b750 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-23 18:04:33 -06:00
Joe Bowser
d28a60ed97 Moving the WebViewClient out, allowing for PhoneGap to not break on empty console.log 2012-01-23 15:04:03 -08:00
Joe Bowser
0890be5815 Moved Chrome Client out of DroidGap.java 2012-01-23 14:42:55 -08:00
Joe Bowser
308a5f1509 Changing to use JS directly. There are issues with this approach, and it should use the KeyboardHandler 2012-01-23 14:21:20 -08:00
Joe Bowser
7904bcc054 Editing a comment about LinearLayoutSoftKeyboardDetect 2012-01-23 14:01:07 -08:00
Joe Bowser
c7e3b46e2e Moving LinearLayoutSoftKeyboardDetect out into its own class and making it more plugin-like 2012-01-23 13:49:55 -08:00
Joe Bowser
490a13d3c4 Removing GapView, since it doesn't actually do anything 2012-01-23 11:57:15 -08:00
Bryce Curtis
1dfe7e59a7 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-20 15:01:46 -06:00
Joe Bowser
a2cdcd47be Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-20 12:43:06 -08:00
Joe Bowser
a42451969f Merge branch 'master' of github.com:cordova/cordova-android 2012-01-20 12:41:29 -08:00
Joe Bowser
7955c6dd02 Merge branch 'master' of github.com:callback/callback-android 2012-01-20 12:39:21 -08:00
macdonst
56096ad00e Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-20 13:38:06 -05:00
Anis Kadri
faacdd6b02 Merge pull request #1 from pehrlich/master
documentation updates
2012-01-17 16:20:31 -08:00
Peter Ehrlich
bdd7449af3 documentation additions 2012-01-17 16:31:08 -05:00
Anis Kadri
64c462c8ad fixing whitelist handling 2012-01-13 17:29:46 -08:00
Joe Bowser
cb0b054079 Merge pull request #3 from alunny/preferences
add support for <preference name="fullscreen"> to res/xml/phonegap.xml
2012-01-10 13:09:04 -08:00
Joe Bowser
41b49df944 Merge pull request #2 from alunny/with-tests
adding JUnit dependency
2012-01-10 13:01:11 -08:00
alunny
ffa76246e3 making preference reading code more robust 2012-01-09 17:31:58 -08:00
alunny
3af4d6b139 using preference=fullscreen for fullscreen view
involves loading configuration before the layout is set up
2012-01-09 17:31:50 -08:00
alunny
752b1b0e30 reading preferences from phonegap.xml
adds PreferenceNode and PreferenceSet classes as wrappers for the W3C
config.xml <preference> nodes

populates a PreferenceSet @preferences member
2012-01-09 17:29:50 -08:00
alunny
d91beb5ad9 adding JUnit dependency
* framework/libs/junit-4.10.jar
* `ant test` task for running junit tests on jar
* updates to LICENSE and NOTICE files
2012-01-09 17:14:26 -08:00
Bryce Curtis
8db5e06c62 Fix CB-135 Multithreaded access on CallbackServer javascript object. 2012-01-06 22:23:49 -06:00
Joe Bowser
bc309c9f00 Merge conflicts with something on the official repo, moving old pull request in 2012-01-06 15:52:09 -08:00
Joe Bowser
9078fe17b5 Merge pull request #40 from infil00p/master
Clean Merge of Classic Render Mode
2012-01-06 15:48:59 -08:00
macdonst
3172ae4525 Merge branch 'master' of git://github.com/cordova/cordova-android 2012-01-06 16:33:20 -05:00
macdonst
58774addad CB-145: Android contact.save() crashes for native contacts. 2012-01-07 05:33:02 +08:00
bcurtis
8c191331ae Merge branch 'master' of github.com:cordova/cordova-android 2012-01-05 15:21:16 -06:00
Bryce Curtis
7f7c211769 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-05 15:08:43 -06:00
Bryce Curtis
51bf8c39af Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-01-05 14:42:41 -06:00
Jukka Zitting
4bba9ac5a0 Minor incubation disclaimer fix. 2012-01-05 21:39:18 +01:00
Jukka Zitting
e9eb08486a README.md: Replace "PhoneGap" with "Cordova" and add incubation disclaimer
(This is a test commit to for checking the git push problem by Bryce)
2012-01-05 21:33:26 +01:00
Bryce Curtis
3466ef6dfd Merge pull request #1 from obrand/basic-auth
Added authentication framework
2012-01-05 09:27:02 -08:00
Olivier Brand
36bca7d609 Renamed crdentials/principals to userName/password 2012-01-05 08:26:54 -08:00
Joe Bowser
cc04b54adf Merge branch 'master' of github.com:callback/callback-android 2012-01-04 16:02:03 -08:00
Olivier Brand
e96ae91800 Added authentication framework 2012-01-04 13:47:44 -08:00
macdonst
1d5af102c7 Camera default destination should be FILE_URI 2012-01-05 03:29:55 +08:00
macdonst
b106d2cae8 Proved generating sqlite database path to open database without permission error 2012-01-05 01:50:56 +08:00
macdonst
c66142d6b8 Fixing issue with FileTransfer.upload when the passed in url contains a ? 2012-01-04 00:48:29 +08:00
macdonst
5fac30ea34 Merge pull request #58 from libbybaldwin/add-compass-demo-android
add compass demo for Android
2011-12-22 10:01:55 -08:00
macdonst
fae551f0ce Fix NullPointerException in DroidGap.onMeasure()
It looks like on some devices the onMeasure() method is called before the callbackServer is instantiated. This causes a NullPointerException which kills the application.
2011-12-22 09:51:11 +08:00
Libby Baldwin
65e3a8a453 add compass demo for Android 2011-12-19 18:30:54 -08:00
Joe Bowser
2094854588 Merge branch 'master' of github.com:callback/callback-android 2011-11-29 14:04:17 -08:00
Joe Bowser
feff655530 Fixing merge error with the setInitialScale 2011-11-25 14:40:08 -08:00
Joe Bowser
71ea25f40a Fixing scale, setting legacy scale 2011-11-25 14:38:11 -08:00
Joe Bowser
7840448133 Work-around Feature for Classic PhoneGap 320x480 resolution 2011-11-25 14:38:11 -08:00
macdonst
e77e552293 Fix for Issue #33: onReceivedError incorrectly sets openExternal to true 2011-11-25 14:38:09 -08:00
William Shen
5ceb6e2cfa Changed createCaptureFile to explicitly check for PNG and to throw an IllegalArgumentException if it is not a JPEG nor a PNG 2011-11-25 14:38:09 -08:00
Bryce Curtis
035ad08c69 Optimize enumerations as suggested by @plowman. 2011-11-25 14:38:08 -08:00
Bryce Curtis
80d0a0cb4c Change API to postMessage() to call a plugin's onMessage() method. 2011-11-25 14:38:07 -08:00
macdonst
05e233bf1d Fix for issue #281 of phonegap/phonegap-android: Detect for localStorage if Java has disabled it 2011-11-25 14:38:06 -08:00
178 changed files with 16491 additions and 7710 deletions

11
.gitignore vendored
View File

@@ -1,15 +1,18 @@
.DS_Store
default.properties
gen
assets/www/phonegap.js
assets/www/cordova.js
local.properties
framework/proguard.cfg
framework/phonegap.jar
framework/cordova.jar
framework/cordova-*.jar
framework/phonegap-*.jar
framework/bin
framework/test/org/apache/cordova/*.class
framework/assets/www/.DS_Store
framework/assets/www/cordova-*.js
framework/assets/www/phonegap-*.js
example
test
./test
tmp
*.tmp
*.tmp

View File

@@ -199,4 +199,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.

1
NOTICE
View File

@@ -3,4 +3,3 @@ Copyright 2011 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org)

View File

@@ -1,7 +1,16 @@
PhoneGap Android
Cordova Android
===
PhoneGap Android is an Android application library that allows for PhoneGap based projects to be built for the Android Platform. PhoneGap based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
Cordova Android is an Android application library that allows for Cordova based projects to be built for the Android Platform. Cordova based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
Apache Cordova is an effort undergoing incubation at The Apache
Software Foundation (ASF), sponsored by the Apache Incubator project.
Incubation is required of all newly accepted projects until a further
review indicates that the infrastructure, communications, and decision
making process have stabilized in a manner consistent with other
successful ASF projects. While incubation status is not necessarily
a reflection of the completeness or stability of the code, it does
indicate that the project has yet to be fully endorsed by the ASF.
Requires
---
@@ -10,25 +19,35 @@ Requires
- Apache ANT
- Android SDK [http://developer.android.com](http://developer.android.com)
PhoneGap Android Developer Tools
Building
---
The PhoneGap developer tooling is split between general tooling and project level tooling.
To create your cordova.jar, run in the framework directory:
android update project -p . -t android-15
ant jar
Cordova Android Developer Tools
---
The Cordova developer tooling is split between general tooling and project level tooling.
General Commands
./bin/create [path package activity] ... create the ./example app or a phonegap android project
./bin/create [path package activity] ... create the ./example app or a cordova android project
./bin/bench ............................ generate a bench proj
./bin/autotest ......................... test the cli tools
./bin/test ............................. run mobile-spec
Project Commands
These commands live in a generated PhoneGap Android project.
These commands live in a generated Cordova Android project.
./phonegap/debug [path] ..................... install to first device
./phonegap/emulate .......................... start avd (emulator) named default
./phonegap/log .............................. starts logcat
./cordovap/debug [path] ..................... install to first device
./cordova/emulate .......................... start avd (emulator) named default
./cordova/log .............................. starts logcat
Running the Example Project
---
@@ -41,29 +60,29 @@ Create the example project and build it to the first device:
./bin/create
cd example
./phonegap/debug
./cordova/debug
Start adb logcat (console.log calls output here):
./phonegap/log
./cordova/log
Running the [callback/callback-test](http://github.com/callback/callback-test) tests:
---
./bin/test
Creating a new PhoneGap Android Project
Creating a new Cordova Android Project
---
./bin/create ~/Desktop/myapp com.phonegap.special MyApp
Importing a PhoneGap Android Project into Eclipse
Importing a Cordova Android Project into Eclipse
----
1. File > New > Project...
2. Android > Android Project
3. Create project from existing source (point to the generated app found in tmp/android)
4. Right click on libs/phonegap.jar and add to build path
4. Right click on libs/cordova.jar and add to build path
5. Right click on the project root: Run as > Run Configurations
6. Click on the Target tab and select Manual (this way you can choose the emulator or device to build to)

View File

@@ -1 +1 @@
1.3.0
1.6.0

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,23 @@ then
rm -rf $PROJECT_PATH
fi
# update the phonegap-android framework for the desired target
# update the cordova-android framework for the desired target
android update project --target $TARGET --path ./framework
# compile phonegap.js and phonegap.jar
# compile cordova.js and cordova.jar
cd ./framework && ant jar && cd ../
# copy all the bin scripts etc in there
cp -R ./bin/templates/project/ $PROJECT_PATH
# copy in phonegap.js
cp ./framework/assets/www/phonegap-$VERSION.js $PROJECT_PATH/.phonegap/android/phonegap-$VERSION.js
# copy in cordova.js
cp ./framework/assets/www/cordova-$VERSION.js $PROJECT_PATH/.cordova/android/cordova-$VERSION.js
# copy in phonegap.jar
cp ./framework/phonegap-$VERSION.jar $PROJECT_PATH/.phonegap/android/phonegap-$VERSION.jar
# copy in cordova.jar
cp ./framework/cordova-$VERSION.jar $PROJECT_PATH/.cordova/android/cordova-$VERSION.jar
# app properties
cat > $PROJECT_PATH/.phonegap/config <<eom
cat > $PROJECT_PATH/.cordova/config <<eom
VERSION=$VERSION
PROJECT_PATH=$PROJECT_PATH
PACKAGE=$PACKAGE
@@ -43,4 +43,4 @@ ACTIVITY=$ACTIVITY
TARGET=$TARGET
eom
(cd $PROJECT_PATH && ./phonegap/create)
(cd $PROJECT_PATH && ./cordova/create)

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,17 @@ MANIFEST_PATH=./AndroidManifest.xml
# create the project
android create project --target $TARGET --path . --package $PACKAGE --activity $ACTIVITY
# copy all the phonegap scripts etc in there
cp -R ./phonegap/templates/project/* .
# copy all the cordova scripts etc in there
cp -R ./cordova/templates/project/* .
# copy in phonegap.js
cp ./.phonegap/android/phonegap-$VERSION.js ./assets/www
# copy in cordova.js
cp ./.cordova/android/cordova-$VERSION.js ./assets/www
# copy in phonegap.jar
cp ./.phonegap/android/phonegap-$VERSION.jar ./libs
# copy in cordova.jar
cp ./.cordova/android/cordova-$VERSION.jar ./libs
# copy in default activity
cat ./phonegap/templates/Activity.java > $ACTIVITY_PATH
cat ./cordova/templates/Activity.java > $ACTIVITY_PATH
# interpolate the acivity name and package
find "$ACTIVITY_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i -e "s/__ACTIVITY__/${ACTIVITY}/g"

View File

@@ -1,6 +1,6 @@
#! /bin/sh
. ./.phonegap/config
. ./.cordova/config
# if there are no devices listed then emulate

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" charset="utf-8">
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="cordova-1.6.0"></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>
@@ -29,8 +29,12 @@
<a href="#" class="btn large" onclick="beep();">Beep</a>
<a href="#" class="btn large" onclick="vibrate();">Vibrate</a>
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
<a href="#" class="btn large" onclick="get_contacts();">Get Phone's Contacts</a>
<a href="#" class="btn large" onclick="check_network();">Check Network</a>
<a href="#" class="btn large" onclick="get_contacts();return false;">Get Phone's Contacts</a>
<a href="#" class="btn large" onclick="check_network();return false;">Check Network</a>
<dl>
<dt>Compass Heading:</dt><dd id="h">Off</dd>
</dl>
<a href="#" class="btn large" onclick="toggleCompass();return false;">Toggle Compass</a>
<div id="viewport" class="viewport" style="display: none;">
<img style="width:60px;height:60px" id="test_img" src="" />
</div>

View File

@@ -119,6 +119,25 @@ function check_network() {
confirm('Connection type:\n ' + states[networkState]);
}
var watchID = null;
function updateHeading(h) {
document.getElementById('h').innerHTML = h.magneticHeading;
}
function toggleCompass() {
if (watchID !== null) {
navigator.compass.clearWatch(watchID);
watchID = null;
updateHeading({ magneticHeading : "Off"});
} else {
var options = { frequency: 1000 };
watchID = navigator.compass.watchHeading(updateHeading, function(e) {
alert('Compass Error: ' + e.code);
}, options);
}
}
function init() {
// the next line makes it impossible to see Contacts on the HTC Evo since it
// doesn't have a scroll button

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<phonegap>
<cordova>
<access origin="http://127.0.0.1*"/>
<log level="DEBUG"/>
</phonegap>
</cordova>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<plugins>
<plugin name="App" value="org.apache.cordova.App"/>
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
<plugin name="Device" value="org.apache.cordova.Device"/>
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
<plugin name="File" value="org.apache.cordova.FileUtils"/>
<plugin name="Network Status" value="org.apache.cordova.NetworkManager"/>
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage"/>
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
<plugin name="Capture" value="org.apache.cordova.Capture"/>
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
</plugins>

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,102 +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", []);
};
/**
* Override the default behavior of the Android back button.
* If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
*
* Note: The user should not have to call this method. Instead, when the user
* registers for the "backbutton" event, this is automatically done.
*
* @param override T=override, F=cancel override
*/
App.prototype.overrideBackbutton = function(override) {
PhoneGap.exec(null, null, "App", "overrideBackbutton", [override]);
};
/**
* Exit and terminate the application.
*/
App.prototype.exitApp = function() {
return PhoneGap.exec(null, null, "App", "exitApp", []);
};
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.DATA_URL;
}
if (options.sourceType === null || typeof options.sourceType === "undefined") {
options.sourceType = Camera.PictureSourceType.CAMERA;
}
if (options.encodingType === null || typeof options.encodingType === "undefined") {
options.encodingType = Camera.EncodingType.JPEG;
}
if (options.mediaType === null || typeof options.mediaType === "undefined") {
options.mediaType = Camera.MediaType.PICTURE;
}
if (options.targetWidth === null || typeof options.targetWidth === "undefined") {
options.targetWidth = -1;
}
else if (typeof options.targetWidth === "string") {
var width = new Number(options.targetWidth);
if (isNaN(width) === false) {
options.targetWidth = width.valueOf();
}
}
if (options.targetHeight === null || typeof options.targetHeight === "undefined") {
options.targetHeight = -1;
}
else if (typeof options.targetHeight === "string") {
var height = new Number(options.targetHeight);
if (isNaN(height) === false) {
options.targetHeight = height.valueOf();
}
}
PhoneGap.exec(successCallback, errorCallback, "Camera", "takePicture", [options]);
};
PhoneGap.addConstructor(function() {
if (typeof navigator.camera === "undefined") {
navigator.camera = new Camera();
}
});
}

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,116 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
if (!PhoneGap.hasResource("device")) {
PhoneGap.addResource("device");
/**
* This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
* phone, etc.
* @constructor
*/
var Device = function() {
this.available = PhoneGap.available;
this.platform = null;
this.version = null;
this.name = null;
this.uuid = null;
this.phonegap = null;
var me = this;
this.getInfo(
function(info) {
me.available = true;
me.platform = info.platform;
me.version = info.version;
me.name = info.name;
me.uuid = info.uuid;
me.phonegap = info.phonegap;
PhoneGap.onPhoneGapInfoReady.fire();
},
function(e) {
me.available = false;
console.log("Error initializing PhoneGap: " + e);
alert("Error initializing PhoneGap: "+e);
});
};
/**
* Get device info
*
* @param {Function} successCallback The function to call when the heading data is available
* @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
*/
Device.prototype.getInfo = function(successCallback, errorCallback) {
// successCallback required
if (typeof successCallback !== "function") {
console.log("Device Error: successCallback is not a function");
return;
}
// errorCallback optional
if (errorCallback && (typeof errorCallback !== "function")) {
console.log("Device Error: errorCallback is not a function");
return;
}
// Get info
PhoneGap.exec(successCallback, errorCallback, "Device", "getDeviceInfo", []);
};
/*
* DEPRECATED
* This is only for Android.
*
* You must explicitly override the back button.
*/
Device.prototype.overrideBackButton = function() {
console.log("Device.overrideBackButton() is deprecated. Use App.overrideBackbutton(true).");
navigator.app.overrideBackbutton(true);
};
/*
* DEPRECATED
* This is only for Android.
*
* This resets the back button to the default behaviour
*/
Device.prototype.resetBackButton = function() {
console.log("Device.resetBackButton() is deprecated. Use App.overrideBackbutton(false).");
navigator.app.overrideBackbutton(false);
};
/*
* DEPRECATED
* This is only for Android.
*
* This terminates the activity!
*/
Device.prototype.exitApp = function() {
console.log("Device.exitApp() is deprecated. Use App.exitApp().");
navigator.app.exitApp();
};
PhoneGap.addConstructor(function() {
if (typeof navigator.device === "undefined") {
navigator.device = window.device = new Device();
}
});
}

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.3.0.js"></script>
<script src="cordova-1.6.0.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,75 +108,68 @@
-->
<import file="${sdk.dir}/tools/ant/build.xml" />
<target name="check-javascript" depends="build-javascript">
<delete dir="assets/lib"/>
<mkdir dir="assets/lib"/>
<echo file="assets/lib/lint.js">var alert=function(){},device={},Element={},debug={};</echo>
<concat destfile="assets/lib/phonegap-lint.js" append="true">
<fileset dir="assets/lib">
<include name="lint.js" />
</fileset>
<fileset dir="assets/www">
<include name="phonegap-${version}.js" />
</fileset>
</concat>
<exec executable="cmd" os="Windows 7">
<arg value="/c"/>
<arg value="java"/>
<arg value="-cp"/>
<arg value="${basedir}/util/js.jar"/>
<arg value="org.mozilla.javascript.tools.shell.Main"/>
<arg value="${basedir}/util/jslint.js"/>
<arg value="${basedir}/js/lib/phonegap-lint.js"/>
</exec>
<exec executable="java" os="Mac OS X">
<arg value="-cp"/>
<arg value="../util/js.jar"/>
<arg value="org.mozilla.javascript.tools.shell.Main"/>
<arg value="../util/jslint.js"/>
<arg value="assets/lib/phonegap-lint.js"/>
</exec>
</target>
<!-- Combine JavaScript files into one phonegap-uncompressed.js file. -->
<target name="build-javascript">
<!-- Combine JavaScript files into one cordova-uncompressed.js file. -->
<target name="build-javascript" depends="clean">
<!-- Clean up existing files -->
<!--<delete file="assets/www/phonegap_${version}.js"/>-->
<!--<delete file="assets/www/cordova_${version}.js"/>-->
<!-- Create uncompressed JS file -->
<concat destfile="assets/www/phonegap-${version}.js">
<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" /> -->
</replaceregexp>
<!-- This is sketchy, but it works, ${dblQuote} does not -->
<replaceregexp match="phonegapVersion = [\u0022].*[\u0022];" replace='phonegapVersion = ${dblQuote}${version}${dblQuote};' byline="true">
<fileset file="src/com/phonegap/Device.java" />
<replaceregexp match="cordovaVersion = [\u0022].*[\u0022];" replace='cordovaVersion = ${dblQuote}${version}${dblQuote};' byline="true">
<fileset file="src/org/apache/cordova/Device.java" />
</replaceregexp>
<!-- Delete temp file -->
<!--<delete file="assets/www/phonegap-tmp.js"/>-->
</target>
<!-- Build PhoneGap jar file that includes all native code, and PhoneGap JS file
<!-- Build Cordova jar file that includes all native code, and Cordova JS file
that includes all JavaScript code.
-->
<target name="jar" depends="build-javascript, -compile">
<jar jarfile="phonegap-${version}.jar" basedir="bin/classes" excludes="com/phonegap/R.class,com/phonegap/R$*.class"/>
<jar jarfile="cordova-${version}.jar" basedir="bin/classes" excludes="org/apache/cordova/R.class,org/apache/cordova/R$*.class"/>
</target>
<target name="phonegap_debug" depends="build-javascript, debug">
<!-- tests for Java files -->
<property name="test.dir" location="test/org/apache/cordova" />
<path id="test.classpath">
<!-- requires both junit and cordova -->
<pathelement location="libs/junit-4.10.jar" />
<pathelement location="cordova-${version}.jar" />
<pathelement location="${test.dir}" />
</path>
<target name="compile-test">
<javac srcdir="${test.dir}" >
<classpath refid="test.classpath" />
</javac>
</target>
<target name="phonegap_release" depends="build-javascript, release">
<target name="test" depends="jar, compile-test">
<junit showoutput="true">
<classpath refid="test.classpath" />
<formatter type="brief" usefile="false" />
<batchtest fork="yes">
<fileset dir="${test.dir}">
<include name="*Test.java" />
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
</target>
<target name="cordova_debug" depends="build-javascript, debug">
</target>
<target name="cordova_release" depends="build-javascript, release">
</target>
</project>

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>

50
framework/res/xml/plugins.xml Normal file → Executable file
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,38 +0,0 @@
package com.phonegap;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.EditText;
public class GapView extends WebView {
public GapView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void attachViewToParent(View child, int index, ViewGroup.LayoutParams params)
{
if(child.getClass() != EditText.class)
super.attachViewToParent(child, index, params);
else
{
super.attachViewToParent(child, index, params);
}
}
@Override
protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params)
{
return super.addViewInLayout(child, index, params);
}
@Override
protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout)
{
return super.addViewInLayout(child, index, params);
}
}

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

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

@@ -0,0 +1,69 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
/**
* The Class AuthenticationToken defines the userName and password to be used for authenticating a web resource
*/
public class AuthenticationToken {
private String userName;
private String password;
/**
* Gets the user name.
*
* @return the user name
*/
public String getUserName() {
return userName;
}
/**
* Sets the user name.
*
* @param userName
* the new user name
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* Gets the password.
*
* @return the password
*/
public String getPassword() {
return password;
}
/**
* Sets the password.
*
* @param password
* the new password
*/
public void setPassword(String password) {
this.password = password;
}
}

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();
@@ -314,9 +314,10 @@ public class CallbackServer implements Runnable {
* @return int
*/
public int getSize() {
int size = this.javascript.size();
//System.out.println("getSize() = " + size);
return size;
synchronized(this) {
int size = this.javascript.size();
return size;
}
}
/**
@@ -325,17 +326,16 @@ public class CallbackServer implements Runnable {
* @return String
*/
public String getJavascript() {
if (this.javascript.size() == 0) {
return null;
}
String statement = this.javascript.remove(0);
//System.out.println("CallbackServer.getJavascript() = " + statement);
if (this.javascript.size() == 0) {
synchronized (this) {
this.empty = true;
}
}
return statement;
synchronized(this) {
if (this.javascript.size() == 0) {
return null;
}
String statement = this.javascript.remove(0);
if (this.javascript.size() == 0) {
this.empty = true;
}
return statement;
}
}
/**
@@ -344,12 +344,11 @@ public class CallbackServer implements Runnable {
* @param statement
*/
public void sendJavascript(String statement) {
//System.out.println("CallbackServer.sendJavascript("+statement+")");
this.javascript.add(statement);
synchronized (this) {
this.empty = false;
this.notify();
}
synchronized (this) {
this.javascript.add(statement);
this.empty = false;
this.notify();
}
}
/* The Following code has been modified from original implementation of URLEncoder */

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;
@@ -101,23 +100,20 @@ public class CameraLauncher extends Plugin {
try {
if (action.equals("takePicture")) {
int srcType = CAMERA;
int destType = DATA_URL;
int destType = FILE_URI;
this.targetHeight = 0;
this.targetWidth = 0;
this.encodingType = JPEG;
this.mediaType = PICTURE;
this.mQuality = 80;
JSONObject options = args.optJSONObject(0);
if (options != null) {
srcType = options.getInt("sourceType");
destType = options.getInt("destinationType");
this.targetHeight = options.getInt("targetHeight");
this.targetWidth = options.getInt("targetWidth");
this.encodingType = options.getInt("encodingType");
this.mediaType = options.getInt("mediaType");
this.mQuality = options.getInt("quality");
}
this.mQuality = args.getInt(0);
destType = args.getInt(1);
srcType = args.getInt(2);
this.targetWidth = args.getInt(3);
this.targetHeight = args.getInt(4);
this.encodingType = args.getInt(5);
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;
}
@@ -819,50 +823,49 @@ public class ContactAccessorSdk5 extends ContactAccessor {
public String save(JSONObject contact) {
AccountManager mgr = AccountManager.get(mApp);
Account[] accounts = mgr.getAccounts();
Account account = null;
String accountName = null;
String accountType = null;
if (accounts.length == 1)
account = accounts[0];
else if (accounts.length > 1) {
for(Account a : accounts){
if(a.type.contains("eas")&& a.name.matches(EMAIL_REGEXP)) /*Exchange ActiveSync*/
{
account = a;
break;
}
}
if(account == null){
for(Account a : accounts){
if(a.type.contains("com.google") && a.name.matches(EMAIL_REGEXP)) /*Google sync provider*/
{
account = a;
break;
}
}
}
if(account == null){
for(Account a : accounts){
if(a.name.matches(EMAIL_REGEXP)) /*Last resort, just look for an email address...*/
{
account = a;
break;
}
}
}
if (accounts.length == 1) {
accountName = accounts[0].name;
accountType = accounts[0].type;
}
if(account == null) {
return null;
else if (accounts.length > 1) {
for(Account a : accounts) {
if(a.type.contains("eas")&& a.name.matches(EMAIL_REGEXP)) /*Exchange ActiveSync*/ {
accountName = a.name;
accountType = a.type;
break;
}
}
if(accountName == null){
for(Account a : accounts){
if(a.type.contains("com.google") && a.name.matches(EMAIL_REGEXP)) /*Google sync provider*/ {
accountName = a.name;
accountType = a.type;
break;
}
}
}
if(accountName == null){
for(Account a : accounts){
if(a.name.matches(EMAIL_REGEXP)) /*Last resort, just look for an email address...*/ {
accountName = a.name;
accountType = a.type;
break;
}
}
}
}
String id = getJsonString(contact, "id");
// Create new contact
if (id == null) {
return createNewContact(contact, account);
return createNewContact(contact, accountType, accountName);
}
// Modify existing contact
else {
return modifyContact(id, contact, account);
return modifyContact(id, contact, accountType, accountName);
}
}
@@ -873,7 +876,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
* @param contact the contact to be saved
* @param account the account to be saved under
*/
private String modifyContact(String id, JSONObject contact, Account account) {
private String modifyContact(String id, JSONObject contact, String accountType, String accountName) {
// Get the RAW_CONTACT_ID which is needed to insert new values in an already existing contact.
// But not needed to update existing values.
int rawId = (new Integer(getJsonString(contact,"rawId"))).intValue();
@@ -883,8 +886,8 @@ public class ContactAccessorSdk5 extends ContactAccessor {
//Add contact type
ops.add(ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.build());
// Modify name
@@ -1427,14 +1430,14 @@ public class ContactAccessorSdk5 extends ContactAccessor {
* @param contact the contact to be saved
* @param account the account to be saved under
*/
private String createNewContact(JSONObject contact, Account account) {
private String createNewContact(JSONObject contact, String accountType, String accountName) {
// Create a list of attributes to add to the contact database
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
//Add contact type
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.build());
// Add name
@@ -1615,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;
}
@@ -1635,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

@@ -0,0 +1,317 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import org.apache.cordova.api.LOG;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ConsoleMessage;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.GeolocationPermissions.Callback;
import android.widget.EditText;
/**
* This class is the WebChromeClient that implements callbacks for our web view.
*/
public class CordovaChromeClient extends WebChromeClient {
private String TAG = "CordovaLog";
private long MAX_QUOTA = 100 * 1024 * 1024;
private DroidGap ctx;
/**
* Constructor.
*
* @param ctx
*/
public CordovaChromeClient(Context ctx) {
this.ctx = (DroidGap) ctx;
}
/**
* Tell the client to display a javascript alert dialog.
*
* @param view
* @param url
* @param message
* @param result
*/
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx);
dlg.setMessage(message);
dlg.setTitle("Alert");
//Don't let alerts break the back button
dlg.setCancelable(true);
dlg.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
});
dlg.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
result.confirm();
}
});
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
//DO NOTHING
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK)
{
result.confirm();
return false;
}
else
return true;
}
});
dlg.create();
dlg.show();
return true;
}
/**
* Tell the client to display a confirm dialog to the user.
*
* @param view
* @param url
* @param message
* @param result
*/
@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx);
dlg.setMessage(message);
dlg.setTitle("Confirm");
dlg.setCancelable(true);
dlg.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
});
dlg.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
});
dlg.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
result.cancel();
}
});
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
//DO NOTHING
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK)
{
result.cancel();
return false;
}
else
return true;
}
});
dlg.create();
dlg.show();
return true;
}
/**
* Tell the client to display a prompt dialog to the user.
* If the client returns true, WebView will assume that the client will
* handle the prompt dialog and call the appropriate JsPromptResult method.
*
* Since we are hacking prompts for our own purposes, we should not be using them for
* this purpose, perhaps we should hack console.log to do this instead!
*
* @param view
* @param url
* @param message
* @param defaultValue
* @param result
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// Security check to make sure any requests are coming from the page initially
// loaded in webview and not another loaded in an iframe.
boolean reqOk = false;
if (url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0 || ctx.isUrlWhiteListed(url)) {
reqOk = true;
}
// Calling PluginManager.exec() to call a native service using
// prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
JSONArray array;
try {
array = new JSONArray(defaultValue.substring(4));
String service = array.getString(0);
String action = array.getString(1);
String callbackId = array.getString(2);
boolean async = array.getBoolean(3);
String r = ctx.pluginManager.exec(service, action, callbackId, message, async);
result.confirm(r);
} catch (JSONException e) {
e.printStackTrace();
}
}
// Polling for JavaScript messages
else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
String r = ctx.callbackServer.getJavascript();
result.confirm(r);
}
// Calling into CallbackServer
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
String r = "";
if (message.equals("usePolling")) {
r = ""+ ctx.callbackServer.usePolling();
}
else if (message.equals("restartServer")) {
ctx.callbackServer.restartServer();
}
else if (message.equals("getPort")) {
r = Integer.toString(ctx.callbackServer.getPort());
}
else if (message.equals("getToken")) {
r = ctx.callbackServer.getToken();
}
result.confirm(r);
}
// Cordova JS has initialized, so show webview
// (This solves white flash seen when rendering HTML)
else if (reqOk && defaultValue != null && defaultValue.equals("gap_init:")) {
if (ctx.splashscreen != 0) {
ctx.root.setBackgroundResource(0);
}
ctx.appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
result.confirm("OK");
}
// Show dialog
else {
final JsPromptResult res = result;
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx);
dlg.setMessage(message);
final EditText input = new EditText(this.ctx);
if (defaultValue != null) {
input.setText(defaultValue);
}
dlg.setView(input);
dlg.setCancelable(false);
dlg.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String usertext = input.getText().toString();
res.confirm(usertext);
}
});
dlg.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
res.cancel();
}
});
dlg.create();
dlg.show();
}
return true;
}
/**
* Handle database quota exceeded notification.
*
* @param url
* @param databaseIdentifier
* @param currentQuota
* @param estimatedSize
* @param totalUsedQuota
* @param quotaUpdater
*/
@Override
public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
{
LOG.d(TAG, "DroidGap: onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
if( estimatedSize < MAX_QUOTA)
{
//increase for 1Mb
long newQuota = estimatedSize;
LOG.d(TAG, "calling quotaUpdater.updateQuota newQuota: %d", newQuota);
quotaUpdater.updateQuota(newQuota);
}
else
{
// Set the quota to whatever it is and force an error
// TODO: get docs on how to handle this properly
quotaUpdater.updateQuota(currentQuota);
}
}
// console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
@Override
public void onConsoleMessage(String message, int lineNumber, String sourceID)
{
LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
super.onConsoleMessage(message, lineNumber, sourceID);
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
{
if(consoleMessage.message() != null)
LOG.d(TAG, consoleMessage.message());
return super.onConsoleMessage(consoleMessage);
}
@Override
/**
* Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
*
* @param origin
* @param callback
*/
public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false);
}
}

View File

@@ -0,0 +1,310 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import org.apache.cordova.api.LOG;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.util.Log;
import android.view.View;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;
/**
* This class is the WebViewClient that implements callbacks for our web view.
*/
public class CordovaWebViewClient extends WebViewClient {
private static final String TAG = "Cordova";
DroidGap ctx;
private boolean doClearHistory = false;
/**
* Constructor.
*
* @param ctx
*/
public CordovaWebViewClient(DroidGap ctx) {
this.ctx = ctx;
}
/**
* Give the host application a chance to take over the control when a new url
* is about to be loaded in the current WebView.
*
* @param view The WebView that is initiating the callback.
* @param url The url to be loaded.
* @return true to override, false for default behavior
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// First give any plugins the chance to handle the url themselves
if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) {
}
// If dialing phone (tel:5551212)
else if (url.startsWith(WebView.SCHEME_TEL)) {
try {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url));
ctx.startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error dialing "+url+": "+ e.toString());
}
}
// If displaying map (geo:0,0?q=address)
else if (url.startsWith("geo:")) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
ctx.startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error showing map "+url+": "+ e.toString());
}
}
// If sending email (mailto:abc@corp.com)
else if (url.startsWith(WebView.SCHEME_MAILTO)) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
ctx.startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error sending email "+url+": "+ e.toString());
}
}
// If sms:5551212?body=This is the message
else if (url.startsWith("sms:")) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
// Get address
String address = null;
int parmIndex = url.indexOf('?');
if (parmIndex == -1) {
address = url.substring(4);
}
else {
address = url.substring(4, parmIndex);
// If body, then set sms body
Uri uri = Uri.parse(url);
String query = uri.getQuery();
if (query != null) {
if (query.startsWith("body=")) {
intent.putExtra("sms_body", query.substring(5));
}
}
}
intent.setData(Uri.parse("sms:"+address));
intent.putExtra("address", address);
intent.setType("vnd.android-dir/mms-sms");
ctx.startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error sending sms "+url+":"+ e.toString());
}
}
// All else
else {
// If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
// Our app continues to run. When BACK is pressed, our app is redisplayed.
if (url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0 || ctx.isUrlWhiteListed(url)) {
this.ctx.loadUrl(url);
}
// If not our application, let default viewer handle
else {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
ctx.startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error loading url "+url, e);
}
}
}
return true;
}
/**
* On received http auth request.
* The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
*
* @param view
* the view
* @param handler
* the handler
* @param host
* the host
* @param realm
* the realm
*/
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
String realm) {
// get the authentication token
AuthenticationToken token = ctx.getAuthenticationToken(host,realm);
if(token != null) {
handler.proceed(token.getUserName(), token.getPassword());
}
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// Clear history so history.back() doesn't do anything.
// So we can reinit() native side CallbackServer & PluginManager.
view.clearHistory();
this.doClearHistory = true;
}
/**
* Notify the host application that a page has finished loading.
*
* @param view The webview initiating the callback.
* @param url The url of the page.
*/
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
/**
* Because of a timing issue we need to clear this history in onPageFinished as well as
* onPageStarted. However we only want to do this if the doClearHistory boolean is set to
* true. You see when you load a url with a # in it which is common in jQuery applications
* onPageStared is not called. Clearing the history at that point would break jQuery apps.
*/
if (this.doClearHistory) {
view.clearHistory();
this.doClearHistory = false;
}
// Clear timeout flag
this.ctx.loadUrlTimeout++;
// Try firing the onNativeReady event in JS. If it fails because the JS is
// not loaded yet then just set a flag so that the onNativeReady can be fired
// from the JS side when the JS gets to that code.
if (!url.equals("about:blank")) {
ctx.appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}");
this.ctx.postMessage("onNativeReady", null);
}
// Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
if (ctx.appView.getVisibility() == View.INVISIBLE) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2000);
ctx.runOnUiThread(new Runnable() {
public void run() {
if (ctx.splashscreen != 0) {
ctx.root.setBackgroundResource(0);
}
ctx.appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
}
});
} catch (InterruptedException e) {
}
}
});
t.start();
}
// Shutdown if blank loaded
if (url.equals("about:blank")) {
if (this.ctx.callbackServer != null) {
this.ctx.callbackServer.destroy();
}
this.ctx.endActivity();
}
}
/**
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
* The errorCode parameter corresponds to one of the ERROR_* constants.
*
* @param view The WebView that is initiating the callback.
* @param errorCode The error code corresponding to an ERROR_* value.
* @param description A String describing the error.
* @param failingUrl The url that failed to load.
*/
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
LOG.d(TAG, "DroidGap: GapViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
// Clear timeout flag
this.ctx.loadUrlTimeout++;
// Stop "app loading" spinner if showing
this.ctx.spinnerStop();
// Handle error
this.ctx.onReceivedError(errorCode, description, failingUrl);
}
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.ctx.getPackageName();
final PackageManager pm = this.ctx.getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// debug = true
handler.proceed();
return;
} else {
// debug = false
super.onReceivedSslError(view, handler, error);
}
} catch (NameNotFoundException e) {
// When it doubt, lock it out!
super.onReceivedSslError(view, handler, error);
}
}
@Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
/*
* If you do a document.location.href the url does not get pushed on the stack
* so we do a check here to see if the url should be pushed.
*/
if (!this.ctx.peekAtUrlStack().equals(url)) {
this.ctx.pushUrl(url);
}
}
}

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.3.0"; // PhoneGap version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
public static String cordovaVersion = "1.6.0"; // 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;
@@ -57,33 +57,41 @@ public class DirectoryManager {
}
/**
* Get the free disk space on the SD card
* Get the free disk space
*
* @return Size in KB or -1 if not available
*/
protected static long getFreeDiskSpace() {
protected static long getFreeDiskSpace(boolean checkInternal) {
String status = Environment.getExternalStorageState();
long freeSpace = 0;
// If SD card exists
if (status.equals(Environment.MEDIA_MOUNTED)) {
try {
File path = Environment.getExternalStorageDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
freeSpace = availableBlocks*blockSize/1024;
} catch (Exception e) {e.printStackTrace(); }
freeSpace = freeSpaceCalculation(Environment.getExternalStorageDirectory().getPath());
}
// If no SD card, then return -1
else if (checkInternal) {
freeSpace = freeSpaceCalculation("/");
}
// If no SD card and we haven't been asked to check the internal directory then return -1
else {
return -1;
}
return (freeSpace);
return freeSpace;
}
/**
* Given a path return the number of free KB
*
* @param path to the file system
* @return free space in KB
*/
private static long freeSpaceCalculation(String path) {
StatFs stat = new StatFs(path);
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks*blockSize/1024;
}
/**
* Determine if SD card exists.

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,12 +51,10 @@ import android.net.Uri;
import android.util.Log;
import android.webkit.CookieManager;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
public class FileTransfer extends Plugin {
private static final String LOG_TAG = "FileUploader";
private static final String LOG_TAG = "FileTransfer";
private static final String LINE_START = "--";
private static final String LINE_END = "\r\n";
private static final String BOUNDRY = "*****";
@@ -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();
@@ -383,33 +416,39 @@ public class FileTransfer extends Plugin {
file.getParentFile().mkdirs();
// connect to server
URL url = new URL(source);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.connect();
if(this.ctx.isUrlWhiteListed(source))
{
URL url = new URL(source);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
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");
@@ -429,7 +468,12 @@ public class FileTransfer extends Plugin {
return ctx.getContentResolver().openInputStream(uri);
}
else if (path.startsWith("file://")) {
return new FileInputStream(path.substring(7));
int question = path.indexOf("?");
if (question == -1) {
return new FileInputStream(path.substring(7));
} else {
return new FileInputStream(path.substring(7, question));
}
}
else {
return new FileInputStream(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();
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()*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.");
@@ -793,39 +812,34 @@ public class FileUtils extends Plugin {
private JSONObject requestFileSystem(int type) throws IOException, JSONException {
JSONObject fs = new JSONObject();
if (type == TEMPORARY) {
File fp;
fs.put("name", "temporary");
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
fs.put("name", "temporary");
fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/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/"));
// Create the cache dir if it doesn't exist.
File fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
fp.mkdirs();
} else {
throw new IOException("SD Card not mounted");
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/"));
}
}
else if (type == PERSISTENT) {
fs.put("name", "persistent");
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
fs.put("name", "persistent");
fs.put("root", getEntry(Environment.getExternalStorageDirectory()));
} else {
throw new IOException("SD Card not mounted");
fs.put("root", getEntry("/data/data/" + ctx.getPackageName()));
}
}
else if (type == RESOURCE) {
fs.put("name", "resource");
}
else if (type == APPLICATION) {
fs.put("name", "application");
}
else {
throw new IOException("No filesystem of type requested");
}
return fs;
}
@@ -842,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);
@@ -897,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);
@@ -915,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);
@@ -958,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;
}
/**
@@ -984,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) {
@@ -1008,6 +1026,7 @@ public class FileUtils extends Plugin {
return ctx.getContentResolver().openInputStream(uri);
}
else {
path = stripFileProtocol(path);
return new FileInputStream(path);
}
}
@@ -1019,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

@@ -0,0 +1,104 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import org.apache.cordova.api.LOG;
import android.content.Context;
import android.view.View.MeasureSpec;
import android.widget.LinearLayout;
/**
* This class is used to detect when the soft keyboard is shown and hidden in the web view.
*/
public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
private static final String TAG = "SoftKeyboardDetect";
private int oldHeight = 0; // Need to save the old height as not to send redundant events
private int oldWidth = 0; // Need to save old width for orientation change
private int screenWidth = 0;
private int screenHeight = 0;
private DroidGap app = null;
public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) {
super(context);
screenWidth = width;
screenHeight = height;
app = (DroidGap) context;
}
@Override
/**
* Start listening to new measurement events. Fire events when the height
* gets smaller fire a show keyboard event and when height gets bigger fire
* a hide keyboard event.
*
* Note: We are using app.postMessage so that this is more compatible with the API
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LOG.v(TAG, "We are in our onMeasure method");
// Get the current height of the visible part of the screen.
// This height will not included the status bar.\
int width, height;
height = MeasureSpec.getSize(heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
LOG.v(TAG, "Old Height = %d", oldHeight);
LOG.v(TAG, "Height = %d", height);
LOG.v(TAG, "Old Width = %d", oldWidth);
LOG.v(TAG, "Width = %d", width);
// If the oldHeight = 0 then this is the first measure event as the app starts up.
// If oldHeight == height then we got a measurement change that doesn't affect us.
if (oldHeight == 0 || oldHeight == height) {
LOG.d(TAG, "Ignore this event");
}
// Account for orientation change and ignore this event/Fire orientation change
else if(screenHeight == width)
{
int tmp_var = screenHeight;
screenHeight = screenWidth;
screenWidth = tmp_var;
LOG.v(TAG, "Orientation Change");
}
// If the height as gotten bigger then we will assume the soft keyboard has
// gone away.
else if (height > oldHeight) {
if(app != null)
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("cordova.fireDocumentEvent('showkeyboard');");
}
// Update the old height for the next event
oldHeight = height;
oldWidth = width;
}
}

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;
@@ -87,7 +87,7 @@ 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.connectionCallbackId = null;

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