mobile_template 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +28 -0
- data/Rakefile +3 -0
- data/bin/mobile_template +71 -0
- data/lib/mobile_template/version.rb +4 -0
- data/lib/mobile_template.rb +5 -0
- data/mobile_template.gemspec +21 -0
- data/templates/assets/Gemfile +4 -0
- data/templates/assets/config.rb +96 -0
- data/templates/assets/config.ru +4 -0
- data/templates/assets/source/images/vendor/ajax-loader.gif +0 -0
- data/templates/assets/source/images/vendor/ajax-loader.png +0 -0
- data/templates/assets/source/images/vendor/icons-18-black.png +0 -0
- data/templates/assets/source/images/vendor/icons-18-white.png +0 -0
- data/templates/assets/source/images/vendor/icons-36-black.png +0 -0
- data/templates/assets/source/images/vendor/icons-36-white.png +0 -0
- data/templates/assets/source/index.html.erb +2 -0
- data/templates/assets/source/javascripts/app/index.js.coffee +2 -0
- data/templates/assets/source/javascripts/application.js.coffee +5 -0
- data/templates/assets/source/javascripts/vendor/cordova.js +4841 -0
- data/templates/assets/source/javascripts/vendor/jquery.js +9267 -0
- data/templates/assets/source/javascripts/vendor/jquery.mobile.js +7410 -0
- data/templates/assets/source/layout.erb +24 -0
- data/templates/assets/source/stylesheets/application.css.scss +2 -0
- data/templates/assets/source/stylesheets/vendor/jquery.mobile.css.scss +1872 -0
- data/templates/cordova_android/.gitignore +18 -0
- data/templates/cordova_android/LICENSE +202 -0
- data/templates/cordova_android/NOTICE +5 -0
- data/templates/cordova_android/README.md +95 -0
- data/templates/cordova_android/VERSION +1 -0
- data/templates/cordova_android/bin/BOOM +4 -0
- data/templates/cordova_android/bin/autotest +2 -0
- data/templates/cordova_android/bin/bench +29 -0
- data/templates/cordova_android/bin/create +46 -0
- data/templates/cordova_android/bin/create.bat +1 -0
- data/templates/cordova_android/bin/create.js +88 -0
- data/templates/cordova_android/bin/create.xml +79 -0
- data/templates/cordova_android/bin/node_modules/.bin/cake +7 -0
- data/templates/cordova_android/bin/node_modules/.bin/coffee +7 -0
- data/templates/cordova_android/bin/node_modules/.bin/nodeunit +120 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/.npmignore +11 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/LICENSE +22 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/README +48 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/Rakefile +78 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/bin/cake +7 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/bin/coffee +7 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/extras/jsl.conf +44 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/browser.js +75 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/cake.js +76 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/coffee-script.js +135 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/command.js +301 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/grammar.js +591 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/helpers.js +66 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/index.js +8 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/lexer.js +656 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/nodes.js +2289 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/optparse.js +111 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/parser.js +676 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/repl.js +123 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/rewriter.js +363 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/lib/scope.js +120 -0
- data/templates/cordova_android/bin/node_modules/coffee-script/package.json +27 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/.gitignore +5 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/.npmignore +3 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/CONTRIBUTORS.md +60 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/LICENSE +19 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/Makefile +126 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/README.md +432 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/bin/nodeunit +120 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/bin/nodeunit.json +10 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/deps/async.js +623 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/deps/console.log.js +55 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/deps/ejs.js +125 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/deps/json2.js +483 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/examples/browser/nodeunit.js +1757 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/examples/browser/suite1.js +12 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/examples/browser/suite2.js +13 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/examples/browser/test.html +16 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/img/example_fail.png +0 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/img/example_pass.png +0 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/index.js +3 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/assert.js +316 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/core.js +260 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/nodeunit.js +82 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/browser.js +119 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/default.js +123 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/html.js +107 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/index.js +9 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/junit.js +183 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/minimal.js +112 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/reporters/skip_passed.js +105 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/track.js +48 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/types.js +187 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/lib/utils.js +209 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/man1/nodeunit.1 +95 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/nodelint.cfg +4 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/package.json +56 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/share/junit.xml.ejs +19 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/share/license.js +11 -0
- data/templates/cordova_android/bin/node_modules/nodeunit/share/nodeunit.css +70 -0
- data/templates/cordova_android/bin/templates/project/.cordova/android/readme.md +1 -0
- data/templates/cordova_android/bin/templates/project/.cordova/readme.md +3 -0
- data/templates/cordova_android/bin/templates/project/cordova/create +36 -0
- data/templates/cordova_android/bin/templates/project/cordova/debug +9 -0
- data/templates/cordova_android/bin/templates/project/cordova/emulate +12 -0
- data/templates/cordova_android/bin/templates/project/cordova/log +3 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/Activity.java +16 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/AndroidManifest.xml +50 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/assets/www/index.html +42 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/assets/www/main.js +146 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/assets/www/master.css +96 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/res/drawable/icon.png +0 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/res/xml/cordova.xml +5 -0
- data/templates/cordova_android/bin/templates/project/cordova/templates/project/res/xml/plugins.xml +19 -0
- data/templates/cordova_android/bin/test +26 -0
- data/templates/cordova_android/bin/tests/autotest.coffee +4 -0
- data/templates/cordova_android/bin/tests/create.coffee +21 -0
- data/templates/cordova_android/bin/tests/debug.coffee +0 -0
- data/templates/cordova_android/bin/tests/test.coffee +0 -0
- data/templates/cordova_android/framework/.classpath +8 -0
- data/templates/cordova_android/framework/.project +33 -0
- data/templates/cordova_android/framework/AndroidManifest.xml +68 -0
- data/templates/cordova_android/framework/ant.properties +34 -0
- data/templates/cordova_android/framework/assets/js/accelerometer.js +137 -0
- data/templates/cordova_android/framework/assets/js/app.js +89 -0
- data/templates/cordova_android/framework/assets/js/battery.js +134 -0
- data/templates/cordova_android/framework/assets/js/camera.js +168 -0
- data/templates/cordova_android/framework/assets/js/capture.js +203 -0
- data/templates/cordova_android/framework/assets/js/compass.js +168 -0
- data/templates/cordova_android/framework/assets/js/contact.js +310 -0
- data/templates/cordova_android/framework/assets/js/cordova.android.js +4841 -0
- data/templates/cordova_android/framework/assets/js/cordova.js.base +924 -0
- data/templates/cordova_android/framework/assets/js/crypto.js +54 -0
- data/templates/cordova_android/framework/assets/js/device.js +83 -0
- data/templates/cordova_android/framework/assets/js/file.js +1082 -0
- data/templates/cordova_android/framework/assets/js/filetransfer.js +125 -0
- data/templates/cordova_android/framework/assets/js/geolocation.js +209 -0
- data/templates/cordova_android/framework/assets/js/header.txt +19 -0
- data/templates/cordova_android/framework/assets/js/media.js +233 -0
- data/templates/cordova_android/framework/assets/js/network.js +100 -0
- data/templates/cordova_android/framework/assets/js/notification.js +133 -0
- data/templates/cordova_android/framework/assets/js/position.js +100 -0
- data/templates/cordova_android/framework/assets/js/storage.js +439 -0
- data/templates/cordova_android/framework/assets/www/index.html +27 -0
- data/templates/cordova_android/framework/build.xml +216 -0
- data/templates/cordova_android/framework/libs/commons-codec-1.3.jar +0 -0
- data/templates/cordova_android/framework/proguard-project.txt +20 -0
- data/templates/cordova_android/framework/project.properties +14 -0
- data/templates/cordova_android/framework/res/drawable/icon.png +0 -0
- data/templates/cordova_android/framework/res/drawable/splash.png +0 -0
- data/templates/cordova_android/framework/res/layout/main.xml +29 -0
- data/templates/cordova_android/framework/res/values/strings.xml +23 -0
- data/templates/cordova_android/framework/res/xml/cordova.xml +37 -0
- data/templates/cordova_android/framework/res/xml/plugins.xml +37 -0
- data/templates/cordova_android/framework/src/com/phonegap/api/IPlugin.java +27 -0
- data/templates/cordova_android/framework/src/com/phonegap/api/LOG.java +28 -0
- data/templates/cordova_android/framework/src/com/phonegap/api/PhonegapActivity.java +28 -0
- data/templates/cordova_android/framework/src/com/phonegap/api/Plugin.java +27 -0
- data/templates/cordova_android/framework/src/com/phonegap/api/PluginManager.java +35 -0
- data/templates/cordova_android/framework/src/com/phonegap/api/PluginResult.java +53 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/AccelListener.java +311 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/App.java +198 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/AudioHandler.java +364 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/AudioPlayer.java +450 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/AuthenticationToken.java +69 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/BatteryListener.java +156 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/CallbackServer.java +431 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/CameraLauncher.java +500 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/Capture.java +400 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/CompassListener.java +308 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/ContactAccessor.java +198 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/ContactAccessorSdk5.java +1934 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/ContactManager.java +113 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/CordovaChromeClient.java +314 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/CordovaWebViewClient.java +306 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/Device.java +219 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/DirectoryManager.java +161 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/DroidGap.java +1417 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/ExifHelper.java +165 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/FileTransfer.java +458 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/FileUploadResult.java +63 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/FileUtils.java +1048 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/GeoBroker.java +165 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/GeoListener.java +133 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/GpsListener.java +163 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/HttpHandler.java +80 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/LinearLayoutSoftKeyboardDetect.java +104 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/NetworkListener.java +153 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/NetworkManager.java +248 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/Notification.java +366 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/PreferenceNode.java +34 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/PreferenceSet.java +62 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/StandAlone.java +35 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/Storage.java +239 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/TempListener.java +112 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/api/CordovaInterface.java +145 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/api/IPlugin.java +116 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/api/LOG.java +234 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/api/Plugin.java +210 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/api/PluginManager.java +359 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/api/PluginResult.java +119 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/file/EncodingException.java +28 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/file/FileExistsException.java +28 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/file/InvalidModificationException.java +29 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/file/NoModificationAllowedException.java +28 -0
- data/templates/cordova_android/framework/src/org/apache/cordova/file/TypeMismatchException.java +29 -0
- data/templates/cordova_android/framework/test/org/apache/cordova/PreferenceNodeTest.java +53 -0
- data/templates/cordova_android/framework/test/org/apache/cordova/PreferenceSetTest.java +73 -0
- metadata +279 -0
|
@@ -0,0 +1,1417 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
or more contributor license agreements. See the NOTICE file
|
|
4
|
+
distributed with this work for additional information
|
|
5
|
+
regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
to you under the Apache License, Version 2.0 (the
|
|
7
|
+
"License"); you may not use this file except in compliance
|
|
8
|
+
with the License. You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing,
|
|
13
|
+
software distributed under the License is distributed on an
|
|
14
|
+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
KIND, either express or implied. See the License for the
|
|
16
|
+
specific language governing permissions and limitations
|
|
17
|
+
under the License.
|
|
18
|
+
*/
|
|
19
|
+
package org.apache.cordova;
|
|
20
|
+
|
|
21
|
+
import java.io.IOException;
|
|
22
|
+
import java.util.ArrayList;
|
|
23
|
+
import java.util.HashMap;
|
|
24
|
+
import java.util.Hashtable;
|
|
25
|
+
import java.util.Iterator;
|
|
26
|
+
import java.util.Stack;
|
|
27
|
+
import java.util.regex.Matcher;
|
|
28
|
+
import java.util.regex.Pattern;
|
|
29
|
+
|
|
30
|
+
import org.apache.cordova.PreferenceNode;
|
|
31
|
+
import org.apache.cordova.PreferenceSet;
|
|
32
|
+
import org.apache.cordova.api.IPlugin;
|
|
33
|
+
import org.apache.cordova.api.LOG;
|
|
34
|
+
import org.apache.cordova.api.CordovaInterface;
|
|
35
|
+
import org.apache.cordova.api.PluginManager;
|
|
36
|
+
import org.xmlpull.v1.XmlPullParserException;
|
|
37
|
+
|
|
38
|
+
import android.app.Activity;
|
|
39
|
+
import android.app.AlertDialog;
|
|
40
|
+
import android.app.ProgressDialog;
|
|
41
|
+
import android.content.Context;
|
|
42
|
+
import android.content.DialogInterface;
|
|
43
|
+
import android.content.Intent;
|
|
44
|
+
import android.content.res.Configuration;
|
|
45
|
+
import android.content.res.XmlResourceParser;
|
|
46
|
+
import android.database.Cursor;
|
|
47
|
+
import android.graphics.Color;
|
|
48
|
+
import android.media.AudioManager;
|
|
49
|
+
import android.net.Uri;
|
|
50
|
+
import android.os.Bundle;
|
|
51
|
+
import android.view.Display;
|
|
52
|
+
import android.view.KeyEvent;
|
|
53
|
+
import android.view.Menu;
|
|
54
|
+
import android.view.MenuItem;
|
|
55
|
+
import android.view.View;
|
|
56
|
+
import android.view.ViewGroup;
|
|
57
|
+
import android.view.Window;
|
|
58
|
+
import android.view.WindowManager;
|
|
59
|
+
import android.webkit.WebSettings;
|
|
60
|
+
import android.webkit.WebSettings.LayoutAlgorithm;
|
|
61
|
+
import android.webkit.WebView;
|
|
62
|
+
import android.webkit.WebViewClient;
|
|
63
|
+
import android.widget.LinearLayout;
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* This class is the main Android activity that represents the Cordova
|
|
69
|
+
* application. It should be extended by the user to load the specific
|
|
70
|
+
* html file that contains the application.
|
|
71
|
+
*
|
|
72
|
+
* As an example:
|
|
73
|
+
*
|
|
74
|
+
* package org.apache.cordova.examples;
|
|
75
|
+
* import android.app.Activity;
|
|
76
|
+
* import android.os.Bundle;
|
|
77
|
+
* import org.apache.cordova.*;
|
|
78
|
+
*
|
|
79
|
+
* public class Examples extends DroidGap {
|
|
80
|
+
* @Override
|
|
81
|
+
* public void onCreate(Bundle savedInstanceState) {
|
|
82
|
+
* super.onCreate(savedInstanceState);
|
|
83
|
+
*
|
|
84
|
+
* // Set properties for activity
|
|
85
|
+
* super.setStringProperty("loadingDialog", "Title,Message"); // show loading dialog
|
|
86
|
+
* super.setStringProperty("errorUrl", "file:///android_asset/www/error.html"); // if error loading file in super.loadUrl().
|
|
87
|
+
*
|
|
88
|
+
* // Initialize activity
|
|
89
|
+
* super.init();
|
|
90
|
+
*
|
|
91
|
+
* // Clear cache if you want
|
|
92
|
+
* super.appView.clearCache(true);
|
|
93
|
+
*
|
|
94
|
+
* // Load your application
|
|
95
|
+
* super.setIntegerProperty("splashscreen", R.drawable.splash); // load splash.jpg image from the resource drawable directory
|
|
96
|
+
* super.loadUrl("file:///android_asset/www/index.html", 3000); // show splash screen 3 sec before loading app
|
|
97
|
+
* }
|
|
98
|
+
* }
|
|
99
|
+
*
|
|
100
|
+
* Properties: The application can be configured using the following properties:
|
|
101
|
+
*
|
|
102
|
+
* // Display a native loading dialog when loading app. Format for value = "Title,Message".
|
|
103
|
+
* // (String - default=null)
|
|
104
|
+
* super.setStringProperty("loadingDialog", "Wait,Loading Demo...");
|
|
105
|
+
*
|
|
106
|
+
* // Display a native loading dialog when loading sub-pages. Format for value = "Title,Message".
|
|
107
|
+
* // (String - default=null)
|
|
108
|
+
* super.setStringProperty("loadingPageDialog", "Loading page...");
|
|
109
|
+
*
|
|
110
|
+
* // Load a splash screen image from the resource drawable directory.
|
|
111
|
+
* // (Integer - default=0)
|
|
112
|
+
* super.setIntegerProperty("splashscreen", R.drawable.splash);
|
|
113
|
+
*
|
|
114
|
+
* // Set the background color.
|
|
115
|
+
* // (Integer - default=0 or BLACK)
|
|
116
|
+
* super.setIntegerProperty("backgroundColor", Color.WHITE);
|
|
117
|
+
*
|
|
118
|
+
* // Time in msec to wait before triggering a timeout error when loading
|
|
119
|
+
* // with super.loadUrl(). (Integer - default=20000)
|
|
120
|
+
* super.setIntegerProperty("loadUrlTimeoutValue", 60000);
|
|
121
|
+
*
|
|
122
|
+
* // URL to load if there's an error loading specified URL with loadUrl().
|
|
123
|
+
* // Should be a local URL starting with file://. (String - default=null)
|
|
124
|
+
* super.setStringProperty("errorUrl", "file:///android_asset/www/error.html");
|
|
125
|
+
*
|
|
126
|
+
* // Enable app to keep running in background. (Boolean - default=true)
|
|
127
|
+
* super.setBooleanProperty("keepRunning", false);
|
|
128
|
+
*
|
|
129
|
+
* Cordova.xml configuration:
|
|
130
|
+
* Cordova uses a configuration file at res/xml/cordova.xml to specify the following settings.
|
|
131
|
+
*
|
|
132
|
+
* Approved list of URLs that can be loaded into DroidGap
|
|
133
|
+
* <access origin="http://server regexp" subdomains="true" />
|
|
134
|
+
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
|
|
135
|
+
* <log level="DEBUG" />
|
|
136
|
+
*
|
|
137
|
+
* Cordova plugins:
|
|
138
|
+
* Cordova uses a file at res/xml/plugins.xml to list all plugins that are installed.
|
|
139
|
+
* Before using a new plugin, a new element must be added to the file.
|
|
140
|
+
* name attribute is the service name passed to Cordova.exec() in JavaScript
|
|
141
|
+
* value attribute is the Java class name to call.
|
|
142
|
+
*
|
|
143
|
+
* <plugins>
|
|
144
|
+
* <plugin name="App" value="org.apache.cordova.App"/>
|
|
145
|
+
* ...
|
|
146
|
+
* </plugins>
|
|
147
|
+
*/
|
|
148
|
+
public class DroidGap extends Activity implements CordovaInterface {
|
|
149
|
+
public static String TAG = "DroidGap";
|
|
150
|
+
|
|
151
|
+
// The webview for our app
|
|
152
|
+
protected WebView appView;
|
|
153
|
+
protected WebViewClient webViewClient;
|
|
154
|
+
private ArrayList<Pattern> whiteList = new ArrayList<Pattern>();
|
|
155
|
+
private HashMap<String, Boolean> whiteListCache = new HashMap<String,Boolean>();
|
|
156
|
+
|
|
157
|
+
protected LinearLayout root;
|
|
158
|
+
public boolean bound = false;
|
|
159
|
+
public CallbackServer callbackServer;
|
|
160
|
+
protected PluginManager pluginManager;
|
|
161
|
+
protected boolean cancelLoadUrl = false;
|
|
162
|
+
protected ProgressDialog spinnerDialog = null;
|
|
163
|
+
|
|
164
|
+
// The initial URL for our app
|
|
165
|
+
// ie http://server/path/index.html#abc?query
|
|
166
|
+
private String url = null;
|
|
167
|
+
private Stack<String> urls = new Stack<String>();
|
|
168
|
+
|
|
169
|
+
// Url was specified from extras (activity was started programmatically)
|
|
170
|
+
private String initUrl = null;
|
|
171
|
+
|
|
172
|
+
private static int ACTIVITY_STARTING = 0;
|
|
173
|
+
private static int ACTIVITY_RUNNING = 1;
|
|
174
|
+
private static int ACTIVITY_EXITING = 2;
|
|
175
|
+
private int activityState = 0; // 0=starting, 1=running (after 1st resume), 2=shutting down
|
|
176
|
+
|
|
177
|
+
// The base of the initial URL for our app.
|
|
178
|
+
// Does not include file name. Ends with /
|
|
179
|
+
// ie http://server/path/
|
|
180
|
+
String baseUrl = null;
|
|
181
|
+
|
|
182
|
+
// Plugin to call when activity result is received
|
|
183
|
+
protected IPlugin activityResultCallback = null;
|
|
184
|
+
protected boolean activityResultKeepRunning;
|
|
185
|
+
|
|
186
|
+
// Flag indicates that a loadUrl timeout occurred
|
|
187
|
+
int loadUrlTimeout = 0;
|
|
188
|
+
|
|
189
|
+
// Default background color for activity
|
|
190
|
+
// (this is not the color for the webview, which is set in HTML)
|
|
191
|
+
private int backgroundColor = Color.BLACK;
|
|
192
|
+
|
|
193
|
+
/** The authorization tokens. */
|
|
194
|
+
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
* The variables below are used to cache some of the activity properties.
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
// Draw a splash screen using an image located in the drawable resource directory.
|
|
201
|
+
// This is not the same as calling super.loadSplashscreen(url)
|
|
202
|
+
protected int splashscreen = 0;
|
|
203
|
+
|
|
204
|
+
// LoadUrl timeout value in msec (default of 20 sec)
|
|
205
|
+
protected int loadUrlTimeoutValue = 20000;
|
|
206
|
+
|
|
207
|
+
// Keep app running when pause is received. (default = true)
|
|
208
|
+
// If true, then the JavaScript and native code continue to run in the background
|
|
209
|
+
// when another application (activity) is started.
|
|
210
|
+
protected boolean keepRunning = true;
|
|
211
|
+
|
|
212
|
+
// preferences read from cordova.xml
|
|
213
|
+
protected PreferenceSet preferences;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Sets the authentication token.
|
|
217
|
+
*
|
|
218
|
+
* @param authenticationToken
|
|
219
|
+
* the authentication token
|
|
220
|
+
* @param host
|
|
221
|
+
* the host
|
|
222
|
+
* @param realm
|
|
223
|
+
* the realm
|
|
224
|
+
*/
|
|
225
|
+
public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
|
|
226
|
+
|
|
227
|
+
if(host == null) {
|
|
228
|
+
host = "";
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if(realm == null) {
|
|
232
|
+
realm = "";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
authenticationTokens.put(host.concat(realm), authenticationToken);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Removes the authentication token.
|
|
240
|
+
*
|
|
241
|
+
* @param host
|
|
242
|
+
* the host
|
|
243
|
+
* @param realm
|
|
244
|
+
* the realm
|
|
245
|
+
* @return the authentication token or null if did not exist
|
|
246
|
+
*/
|
|
247
|
+
public AuthenticationToken removeAuthenticationToken(String host, String realm) {
|
|
248
|
+
return authenticationTokens.remove(host.concat(realm));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Gets the authentication token.
|
|
253
|
+
*
|
|
254
|
+
* In order it tries:
|
|
255
|
+
* 1- host + realm
|
|
256
|
+
* 2- host
|
|
257
|
+
* 3- realm
|
|
258
|
+
* 4- no host, no realm
|
|
259
|
+
*
|
|
260
|
+
* @param host
|
|
261
|
+
* the host
|
|
262
|
+
* @param realm
|
|
263
|
+
* the realm
|
|
264
|
+
* @return the authentication token
|
|
265
|
+
*/
|
|
266
|
+
public AuthenticationToken getAuthenticationToken(String host, String realm) {
|
|
267
|
+
AuthenticationToken token = null;
|
|
268
|
+
|
|
269
|
+
token = authenticationTokens.get(host.concat(realm));
|
|
270
|
+
|
|
271
|
+
if(token == null) {
|
|
272
|
+
// try with just the host
|
|
273
|
+
token = authenticationTokens.get(host);
|
|
274
|
+
|
|
275
|
+
// Try the realm
|
|
276
|
+
if(token == null) {
|
|
277
|
+
token = authenticationTokens.get(realm);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// if no host found, just query for default
|
|
281
|
+
if(token == null) {
|
|
282
|
+
token = authenticationTokens.get("");
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return token;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Clear all authentication tokens.
|
|
291
|
+
*/
|
|
292
|
+
public void clearAuthenticationTokens() {
|
|
293
|
+
authenticationTokens.clear();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Called when the activity is first created.
|
|
299
|
+
*
|
|
300
|
+
* @param savedInstanceState
|
|
301
|
+
*/
|
|
302
|
+
@Override
|
|
303
|
+
public void onCreate(Bundle savedInstanceState) {
|
|
304
|
+
preferences = new PreferenceSet();
|
|
305
|
+
|
|
306
|
+
// Load Cordova configuration:
|
|
307
|
+
// white list of allowed URLs
|
|
308
|
+
// debug setting
|
|
309
|
+
this.loadConfiguration();
|
|
310
|
+
|
|
311
|
+
LOG.d(TAG, "DroidGap.onCreate()");
|
|
312
|
+
super.onCreate(savedInstanceState);
|
|
313
|
+
|
|
314
|
+
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
|
315
|
+
|
|
316
|
+
if (preferences.prefMatches("fullscreen","true")) {
|
|
317
|
+
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
|
318
|
+
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
319
|
+
} else {
|
|
320
|
+
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
|
|
321
|
+
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
|
|
325
|
+
Display display = getWindowManager().getDefaultDisplay();
|
|
326
|
+
int width = display.getWidth();
|
|
327
|
+
int height = display.getHeight();
|
|
328
|
+
|
|
329
|
+
root = new LinearLayoutSoftKeyboardDetect(this, width, height);
|
|
330
|
+
root.setOrientation(LinearLayout.VERTICAL);
|
|
331
|
+
root.setBackgroundColor(this.backgroundColor);
|
|
332
|
+
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
|
333
|
+
ViewGroup.LayoutParams.FILL_PARENT, 0.0F));
|
|
334
|
+
|
|
335
|
+
// If url was passed in to intent, then init webview, which will load the url
|
|
336
|
+
Bundle bundle = this.getIntent().getExtras();
|
|
337
|
+
if (bundle != null) {
|
|
338
|
+
String url = bundle.getString("url");
|
|
339
|
+
if (url != null) {
|
|
340
|
+
this.initUrl = url;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Setup the hardware volume controls to handle volume control
|
|
344
|
+
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Create and initialize web container.
|
|
349
|
+
*/
|
|
350
|
+
public void init() {
|
|
351
|
+
LOG.d(TAG, "DroidGap.init()");
|
|
352
|
+
|
|
353
|
+
// Create web container
|
|
354
|
+
this.appView = new WebView(DroidGap.this);
|
|
355
|
+
this.appView.setId(100);
|
|
356
|
+
|
|
357
|
+
this.appView.setLayoutParams(new LinearLayout.LayoutParams(
|
|
358
|
+
ViewGroup.LayoutParams.FILL_PARENT,
|
|
359
|
+
ViewGroup.LayoutParams.FILL_PARENT,
|
|
360
|
+
1.0F));
|
|
361
|
+
|
|
362
|
+
this.appView.setWebChromeClient(new CordovaChromeClient(DroidGap.this));
|
|
363
|
+
this.setWebViewClient(this.appView, new CordovaWebViewClient(this));
|
|
364
|
+
|
|
365
|
+
this.appView.setInitialScale(0);
|
|
366
|
+
this.appView.setVerticalScrollBarEnabled(false);
|
|
367
|
+
this.appView.requestFocusFromTouch();
|
|
368
|
+
|
|
369
|
+
// Enable JavaScript
|
|
370
|
+
WebSettings settings = this.appView.getSettings();
|
|
371
|
+
settings.setJavaScriptEnabled(true);
|
|
372
|
+
settings.setJavaScriptCanOpenWindowsAutomatically(true);
|
|
373
|
+
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
|
|
374
|
+
|
|
375
|
+
//Set the nav dump for HTC
|
|
376
|
+
settings.setNavDump(true);
|
|
377
|
+
|
|
378
|
+
// Enable database
|
|
379
|
+
settings.setDatabaseEnabled(true);
|
|
380
|
+
String databasePath = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
|
|
381
|
+
settings.setDatabasePath(databasePath);
|
|
382
|
+
|
|
383
|
+
// Enable DOM storage
|
|
384
|
+
settings.setDomStorageEnabled(true);
|
|
385
|
+
|
|
386
|
+
// Enable built-in geolocation
|
|
387
|
+
settings.setGeolocationEnabled(true);
|
|
388
|
+
|
|
389
|
+
// Add web view but make it invisible while loading URL
|
|
390
|
+
this.appView.setVisibility(View.INVISIBLE);
|
|
391
|
+
root.addView(this.appView);
|
|
392
|
+
setContentView(root);
|
|
393
|
+
|
|
394
|
+
// Clear cancel flag
|
|
395
|
+
this.cancelLoadUrl = false;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Set the WebViewClient.
|
|
400
|
+
*
|
|
401
|
+
* @param appView
|
|
402
|
+
* @param client
|
|
403
|
+
*/
|
|
404
|
+
protected void setWebViewClient(WebView appView, WebViewClient client) {
|
|
405
|
+
this.webViewClient = client;
|
|
406
|
+
appView.setWebViewClient(client);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Look at activity parameters and process them.
|
|
411
|
+
* This must be called from the main UI thread.
|
|
412
|
+
*/
|
|
413
|
+
private void handleActivityParameters() {
|
|
414
|
+
|
|
415
|
+
// If backgroundColor
|
|
416
|
+
this.backgroundColor = this.getIntegerProperty("backgroundColor", Color.BLACK);
|
|
417
|
+
this.root.setBackgroundColor(this.backgroundColor);
|
|
418
|
+
|
|
419
|
+
// If spashscreen
|
|
420
|
+
this.splashscreen = this.getIntegerProperty("splashscreen", 0);
|
|
421
|
+
if ((this.urls.size() == 0) && (this.splashscreen != 0)) {
|
|
422
|
+
root.setBackgroundResource(this.splashscreen);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// If loadUrlTimeoutValue
|
|
426
|
+
int timeout = this.getIntegerProperty("loadUrlTimeoutValue", 0);
|
|
427
|
+
if (timeout > 0) {
|
|
428
|
+
this.loadUrlTimeoutValue = timeout;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// If keepRunning
|
|
432
|
+
this.keepRunning = this.getBooleanProperty("keepRunning", true);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Load the url into the webview.
|
|
437
|
+
*
|
|
438
|
+
* @param url
|
|
439
|
+
*/
|
|
440
|
+
public void loadUrl(String url) {
|
|
441
|
+
|
|
442
|
+
// If first page of app, then set URL to load to be the one passed in
|
|
443
|
+
if (this.initUrl == null || (this.urls.size() > 0)) {
|
|
444
|
+
this.loadUrlIntoView(url);
|
|
445
|
+
}
|
|
446
|
+
// Otherwise use the URL specified in the activity's extras bundle
|
|
447
|
+
else {
|
|
448
|
+
this.loadUrlIntoView(this.initUrl);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Load the url into the webview.
|
|
454
|
+
*
|
|
455
|
+
* @param url
|
|
456
|
+
*/
|
|
457
|
+
private void loadUrlIntoView(final String url) {
|
|
458
|
+
if (!url.startsWith("javascript:")) {
|
|
459
|
+
LOG.d(TAG, "DroidGap.loadUrl(%s)", url);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
this.url = url;
|
|
463
|
+
if (this.baseUrl == null) {
|
|
464
|
+
int i = url.lastIndexOf('/');
|
|
465
|
+
if (i > 0) {
|
|
466
|
+
this.baseUrl = url.substring(0, i+1);
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
this.baseUrl = this.url + "/";
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (!url.startsWith("javascript:")) {
|
|
473
|
+
LOG.d(TAG, "DroidGap: url=%s baseUrl=%s", url, baseUrl);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Load URL on UI thread
|
|
477
|
+
final DroidGap me = this;
|
|
478
|
+
this.runOnUiThread(new Runnable() {
|
|
479
|
+
public void run() {
|
|
480
|
+
|
|
481
|
+
// Init web view if not already done
|
|
482
|
+
if (me.appView == null) {
|
|
483
|
+
me.init();
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Handle activity parameters
|
|
487
|
+
me.handleActivityParameters();
|
|
488
|
+
|
|
489
|
+
// Track URLs loaded instead of using appView history
|
|
490
|
+
me.urls.push(url);
|
|
491
|
+
me.appView.clearHistory();
|
|
492
|
+
|
|
493
|
+
// Create callback server and plugin manager
|
|
494
|
+
if (me.callbackServer == null) {
|
|
495
|
+
me.callbackServer = new CallbackServer();
|
|
496
|
+
me.callbackServer.init(url);
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
me.callbackServer.reinit(url);
|
|
500
|
+
}
|
|
501
|
+
if (me.pluginManager == null) {
|
|
502
|
+
me.pluginManager = new PluginManager(me.appView, me);
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
me.pluginManager.reinit();
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// If loadingDialog property, then show the App loading dialog for first page of app
|
|
509
|
+
String loading = null;
|
|
510
|
+
if (me.urls.size() == 1) {
|
|
511
|
+
loading = me.getStringProperty("loadingDialog", null);
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
loading = me.getStringProperty("loadingPageDialog", null);
|
|
515
|
+
}
|
|
516
|
+
if (loading != null) {
|
|
517
|
+
|
|
518
|
+
String title = "";
|
|
519
|
+
String message = "Loading Application...";
|
|
520
|
+
|
|
521
|
+
if (loading.length() > 0) {
|
|
522
|
+
int comma = loading.indexOf(',');
|
|
523
|
+
if (comma > 0) {
|
|
524
|
+
title = loading.substring(0, comma);
|
|
525
|
+
message = loading.substring(comma+1);
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
title = "";
|
|
529
|
+
message = loading;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
me.spinnerStart(title, message);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Create a timeout timer for loadUrl
|
|
536
|
+
final int currentLoadUrlTimeout = me.loadUrlTimeout;
|
|
537
|
+
Runnable runnable = new Runnable() {
|
|
538
|
+
public void run() {
|
|
539
|
+
try {
|
|
540
|
+
synchronized(this) {
|
|
541
|
+
wait(me.loadUrlTimeoutValue);
|
|
542
|
+
}
|
|
543
|
+
} catch (InterruptedException e) {
|
|
544
|
+
e.printStackTrace();
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// If timeout, then stop loading and handle error
|
|
548
|
+
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
|
|
549
|
+
me.appView.stopLoading();
|
|
550
|
+
LOG.e(TAG, "DroidGap: TIMEOUT ERROR! - calling webViewClient");
|
|
551
|
+
me.webViewClient.onReceivedError(me.appView, -6, "The connection to the server was unsuccessful.", url);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
Thread thread = new Thread(runnable);
|
|
556
|
+
thread.start();
|
|
557
|
+
me.appView.loadUrl(url);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Load the url into the webview after waiting for period of time.
|
|
564
|
+
* This is used to display the splashscreen for certain amount of time.
|
|
565
|
+
*
|
|
566
|
+
* @param url
|
|
567
|
+
* @param time The number of ms to wait before loading webview
|
|
568
|
+
*/
|
|
569
|
+
public void loadUrl(final String url, int time) {
|
|
570
|
+
|
|
571
|
+
// If first page of app, then set URL to load to be the one passed in
|
|
572
|
+
if (this.initUrl == null || (this.urls.size() > 0)) {
|
|
573
|
+
this.loadUrlIntoView(url, time);
|
|
574
|
+
}
|
|
575
|
+
// Otherwise use the URL specified in the activity's extras bundle
|
|
576
|
+
else {
|
|
577
|
+
this.loadUrlIntoView(this.initUrl);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Load the url into the webview after waiting for period of time.
|
|
583
|
+
* This is used to display the splashscreen for certain amount of time.
|
|
584
|
+
*
|
|
585
|
+
* @param url
|
|
586
|
+
* @param time The number of ms to wait before loading webview
|
|
587
|
+
*/
|
|
588
|
+
private void loadUrlIntoView(final String url, final int time) {
|
|
589
|
+
|
|
590
|
+
// Clear cancel flag
|
|
591
|
+
this.cancelLoadUrl = false;
|
|
592
|
+
|
|
593
|
+
// If not first page of app, then load immediately
|
|
594
|
+
if (this.urls.size() > 0) {
|
|
595
|
+
this.loadUrlIntoView(url);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (!url.startsWith("javascript:")) {
|
|
599
|
+
LOG.d(TAG, "DroidGap.loadUrl(%s, %d)", url, time);
|
|
600
|
+
}
|
|
601
|
+
final DroidGap me = this;
|
|
602
|
+
|
|
603
|
+
// Handle activity parameters
|
|
604
|
+
this.runOnUiThread(new Runnable() {
|
|
605
|
+
public void run() {
|
|
606
|
+
if (me.appView == null) {
|
|
607
|
+
me.init();
|
|
608
|
+
}
|
|
609
|
+
me.handleActivityParameters();
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
Runnable runnable = new Runnable() {
|
|
614
|
+
public void run() {
|
|
615
|
+
try {
|
|
616
|
+
synchronized(this) {
|
|
617
|
+
this.wait(time);
|
|
618
|
+
}
|
|
619
|
+
} catch (InterruptedException e) {
|
|
620
|
+
e.printStackTrace();
|
|
621
|
+
}
|
|
622
|
+
if (!me.cancelLoadUrl) {
|
|
623
|
+
me.loadUrlIntoView(url);
|
|
624
|
+
}
|
|
625
|
+
else{
|
|
626
|
+
me.cancelLoadUrl = false;
|
|
627
|
+
LOG.d(TAG, "Aborting loadUrl(%s): Another URL was loaded before timer expired.", url);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
Thread thread = new Thread(runnable);
|
|
632
|
+
thread.start();
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Cancel loadUrl before it has been loaded.
|
|
637
|
+
*/
|
|
638
|
+
public void cancelLoadUrl() {
|
|
639
|
+
this.cancelLoadUrl = true;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Clear the resource cache.
|
|
644
|
+
*/
|
|
645
|
+
public void clearCache() {
|
|
646
|
+
if (this.appView == null) {
|
|
647
|
+
this.init();
|
|
648
|
+
}
|
|
649
|
+
this.appView.clearCache(true);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Clear web history in this web view.
|
|
654
|
+
*/
|
|
655
|
+
public void clearHistory() {
|
|
656
|
+
this.urls.clear();
|
|
657
|
+
this.appView.clearHistory();
|
|
658
|
+
|
|
659
|
+
// Leave current url on history stack
|
|
660
|
+
if (this.url != null) {
|
|
661
|
+
this.urls.push(this.url);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Go to previous page in history. (We manage our own history)
|
|
667
|
+
*
|
|
668
|
+
* @return true if we went back, false if we are already at top
|
|
669
|
+
*/
|
|
670
|
+
public boolean backHistory() {
|
|
671
|
+
|
|
672
|
+
// Check webview first to see if there is a history
|
|
673
|
+
// This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
|
|
674
|
+
if (this.appView.canGoBack()) {
|
|
675
|
+
this.appView.goBack();
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// If our managed history has prev url
|
|
680
|
+
if (this.urls.size() > 1) {
|
|
681
|
+
this.urls.pop(); // Pop current url
|
|
682
|
+
String url = this.urls.pop(); // Pop prev url that we want to load, since it will be added back by loadUrl()
|
|
683
|
+
this.loadUrl(url);
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
@Override
|
|
691
|
+
/**
|
|
692
|
+
* Called by the system when the device configuration changes while your activity is running.
|
|
693
|
+
*
|
|
694
|
+
* @param Configuration newConfig
|
|
695
|
+
*/
|
|
696
|
+
public void onConfigurationChanged(Configuration newConfig) {
|
|
697
|
+
//don't reload the current page when the orientation is changed
|
|
698
|
+
super.onConfigurationChanged(newConfig);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Get boolean property for activity.
|
|
703
|
+
*
|
|
704
|
+
* @param name
|
|
705
|
+
* @param defaultValue
|
|
706
|
+
* @return
|
|
707
|
+
*/
|
|
708
|
+
public boolean getBooleanProperty(String name, boolean defaultValue) {
|
|
709
|
+
Bundle bundle = this.getIntent().getExtras();
|
|
710
|
+
if (bundle == null) {
|
|
711
|
+
return defaultValue;
|
|
712
|
+
}
|
|
713
|
+
Boolean p = (Boolean)bundle.get(name);
|
|
714
|
+
if (p == null) {
|
|
715
|
+
return defaultValue;
|
|
716
|
+
}
|
|
717
|
+
return p.booleanValue();
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Get int property for activity.
|
|
722
|
+
*
|
|
723
|
+
* @param name
|
|
724
|
+
* @param defaultValue
|
|
725
|
+
* @return
|
|
726
|
+
*/
|
|
727
|
+
public int getIntegerProperty(String name, int defaultValue) {
|
|
728
|
+
Bundle bundle = this.getIntent().getExtras();
|
|
729
|
+
if (bundle == null) {
|
|
730
|
+
return defaultValue;
|
|
731
|
+
}
|
|
732
|
+
Integer p = (Integer)bundle.get(name);
|
|
733
|
+
if (p == null) {
|
|
734
|
+
return defaultValue;
|
|
735
|
+
}
|
|
736
|
+
return p.intValue();
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Get string property for activity.
|
|
741
|
+
*
|
|
742
|
+
* @param name
|
|
743
|
+
* @param defaultValue
|
|
744
|
+
* @return
|
|
745
|
+
*/
|
|
746
|
+
public String getStringProperty(String name, String defaultValue) {
|
|
747
|
+
Bundle bundle = this.getIntent().getExtras();
|
|
748
|
+
if (bundle == null) {
|
|
749
|
+
return defaultValue;
|
|
750
|
+
}
|
|
751
|
+
String p = bundle.getString(name);
|
|
752
|
+
if (p == null) {
|
|
753
|
+
return defaultValue;
|
|
754
|
+
}
|
|
755
|
+
return p;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Get double property for activity.
|
|
760
|
+
*
|
|
761
|
+
* @param name
|
|
762
|
+
* @param defaultValue
|
|
763
|
+
* @return
|
|
764
|
+
*/
|
|
765
|
+
public double getDoubleProperty(String name, double defaultValue) {
|
|
766
|
+
Bundle bundle = this.getIntent().getExtras();
|
|
767
|
+
if (bundle == null) {
|
|
768
|
+
return defaultValue;
|
|
769
|
+
}
|
|
770
|
+
Double p = (Double)bundle.get(name);
|
|
771
|
+
if (p == null) {
|
|
772
|
+
return defaultValue;
|
|
773
|
+
}
|
|
774
|
+
return p.doubleValue();
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Set boolean property on activity.
|
|
779
|
+
*
|
|
780
|
+
* @param name
|
|
781
|
+
* @param value
|
|
782
|
+
*/
|
|
783
|
+
public void setBooleanProperty(String name, boolean value) {
|
|
784
|
+
this.getIntent().putExtra(name, value);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Set int property on activity.
|
|
789
|
+
*
|
|
790
|
+
* @param name
|
|
791
|
+
* @param value
|
|
792
|
+
*/
|
|
793
|
+
public void setIntegerProperty(String name, int value) {
|
|
794
|
+
this.getIntent().putExtra(name, value);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Set string property on activity.
|
|
799
|
+
*
|
|
800
|
+
* @param name
|
|
801
|
+
* @param value
|
|
802
|
+
*/
|
|
803
|
+
public void setStringProperty(String name, String value) {
|
|
804
|
+
this.getIntent().putExtra(name, value);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Set double property on activity.
|
|
809
|
+
*
|
|
810
|
+
* @param name
|
|
811
|
+
* @param value
|
|
812
|
+
*/
|
|
813
|
+
public void setDoubleProperty(String name, double value) {
|
|
814
|
+
this.getIntent().putExtra(name, value);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
@Override
|
|
818
|
+
/**
|
|
819
|
+
* Called when the system is about to start resuming a previous activity.
|
|
820
|
+
*/
|
|
821
|
+
protected void onPause() {
|
|
822
|
+
super.onPause();
|
|
823
|
+
|
|
824
|
+
// Don't process pause if shutting down, since onDestroy() will be called
|
|
825
|
+
if (this.activityState == ACTIVITY_EXITING) {
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (this.appView == null) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Send pause event to JavaScript
|
|
834
|
+
this.appView.loadUrl("javascript:try{require('cordova/channel').onPause.fire();}catch(e){console.log('exception firing pause event from native');};");
|
|
835
|
+
|
|
836
|
+
// Forward to plugins
|
|
837
|
+
this.pluginManager.onPause(this.keepRunning);
|
|
838
|
+
|
|
839
|
+
// If app doesn't want to run in background
|
|
840
|
+
if (!this.keepRunning) {
|
|
841
|
+
|
|
842
|
+
// Pause JavaScript timers (including setInterval)
|
|
843
|
+
this.appView.pauseTimers();
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
@Override
|
|
848
|
+
/**
|
|
849
|
+
* Called when the activity receives a new intent
|
|
850
|
+
**/
|
|
851
|
+
protected void onNewIntent(Intent intent) {
|
|
852
|
+
super.onNewIntent(intent);
|
|
853
|
+
|
|
854
|
+
//Forward to plugins
|
|
855
|
+
this.pluginManager.onNewIntent(intent);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
@Override
|
|
859
|
+
/**
|
|
860
|
+
* Called when the activity will start interacting with the user.
|
|
861
|
+
*/
|
|
862
|
+
protected void onResume() {
|
|
863
|
+
super.onResume();
|
|
864
|
+
|
|
865
|
+
if (this.activityState == ACTIVITY_STARTING) {
|
|
866
|
+
this.activityState = ACTIVITY_RUNNING;
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
if (this.appView == null) {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// Send resume event to JavaScript
|
|
875
|
+
this.appView.loadUrl("javascript:try{require('cordova/channel').onResume.fire();}catch(e){console.log('exception firing resume event from native');};");
|
|
876
|
+
|
|
877
|
+
// Forward to plugins
|
|
878
|
+
this.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
|
|
879
|
+
|
|
880
|
+
// If app doesn't want to run in background
|
|
881
|
+
if (!this.keepRunning || this.activityResultKeepRunning) {
|
|
882
|
+
|
|
883
|
+
// Restore multitasking state
|
|
884
|
+
if (this.activityResultKeepRunning) {
|
|
885
|
+
this.keepRunning = this.activityResultKeepRunning;
|
|
886
|
+
this.activityResultKeepRunning = false;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
// Resume JavaScript timers (including setInterval)
|
|
890
|
+
this.appView.resumeTimers();
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
@Override
|
|
895
|
+
/**
|
|
896
|
+
* The final call you receive before your activity is destroyed.
|
|
897
|
+
*/
|
|
898
|
+
public void onDestroy() {
|
|
899
|
+
super.onDestroy();
|
|
900
|
+
|
|
901
|
+
if (this.appView != null) {
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
// Send destroy event to JavaScript
|
|
905
|
+
this.appView.loadUrl("javascript:try{require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
|
|
906
|
+
|
|
907
|
+
// Load blank page so that JavaScript onunload is called
|
|
908
|
+
this.appView.loadUrl("about:blank");
|
|
909
|
+
|
|
910
|
+
// Forward to plugins
|
|
911
|
+
if (this.pluginManager != null) {
|
|
912
|
+
this.pluginManager.onDestroy();
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
this.endActivity();
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Send a message to all plugins.
|
|
922
|
+
*
|
|
923
|
+
* @param id The message id
|
|
924
|
+
* @param data The message data
|
|
925
|
+
*/
|
|
926
|
+
public void postMessage(String id, Object data) {
|
|
927
|
+
|
|
928
|
+
// Forward to plugins
|
|
929
|
+
if (this.pluginManager != null) {
|
|
930
|
+
this.pluginManager.postMessage(id, data);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* @deprecated
|
|
936
|
+
* Add services to res/xml/plugins.xml instead.
|
|
937
|
+
*
|
|
938
|
+
* Add a class that implements a service.
|
|
939
|
+
*
|
|
940
|
+
* @param serviceType
|
|
941
|
+
* @param className
|
|
942
|
+
*/
|
|
943
|
+
@Deprecated
|
|
944
|
+
public void addService(String serviceType, String className) {
|
|
945
|
+
this.pluginManager.addService(serviceType, className);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Send JavaScript statement back to JavaScript.
|
|
950
|
+
* (This is a convenience method)
|
|
951
|
+
*
|
|
952
|
+
* @param message
|
|
953
|
+
*/
|
|
954
|
+
public void sendJavascript(String statement) {
|
|
955
|
+
this.callbackServer.sendJavascript(statement);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* Load the specified URL in the Cordova webview or a new browser instance.
|
|
960
|
+
*
|
|
961
|
+
* NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
|
|
962
|
+
*
|
|
963
|
+
* @param url The url to load.
|
|
964
|
+
* @param openExternal Load url in browser instead of Cordova webview.
|
|
965
|
+
* @param clearHistory Clear the history stack, so new page becomes top of history
|
|
966
|
+
* @param params DroidGap parameters for new app
|
|
967
|
+
*/
|
|
968
|
+
public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) { //throws android.content.ActivityNotFoundException {
|
|
969
|
+
LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
|
|
970
|
+
|
|
971
|
+
// If clearing history
|
|
972
|
+
if (clearHistory) {
|
|
973
|
+
this.clearHistory();
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// If loading into our webview
|
|
977
|
+
if (!openExternal) {
|
|
978
|
+
|
|
979
|
+
// Make sure url is in whitelist
|
|
980
|
+
if (url.startsWith("file://") || url.indexOf(this.baseUrl) == 0 || isUrlWhiteListed(url)) {
|
|
981
|
+
// TODO: What about params?
|
|
982
|
+
|
|
983
|
+
// Clear out current url from history, since it will be replacing it
|
|
984
|
+
if (clearHistory) {
|
|
985
|
+
this.urls.clear();
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
// Load new URL
|
|
989
|
+
this.loadUrl(url);
|
|
990
|
+
}
|
|
991
|
+
// Load in default viewer if not
|
|
992
|
+
else {
|
|
993
|
+
LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list. Loading into browser instead. (URL="+url+")");
|
|
994
|
+
try {
|
|
995
|
+
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
996
|
+
intent.setData(Uri.parse(url));
|
|
997
|
+
this.startActivity(intent);
|
|
998
|
+
} catch (android.content.ActivityNotFoundException e) {
|
|
999
|
+
LOG.e(TAG, "Error loading url "+url, e);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// Load in default view intent
|
|
1005
|
+
else {
|
|
1006
|
+
try {
|
|
1007
|
+
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
1008
|
+
intent.setData(Uri.parse(url));
|
|
1009
|
+
this.startActivity(intent);
|
|
1010
|
+
} catch (android.content.ActivityNotFoundException e) {
|
|
1011
|
+
LOG.e(TAG, "Error loading url "+url, e);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Show the spinner. Must be called from the UI thread.
|
|
1018
|
+
*
|
|
1019
|
+
* @param title Title of the dialog
|
|
1020
|
+
* @param message The message of the dialog
|
|
1021
|
+
*/
|
|
1022
|
+
public void spinnerStart(final String title, final String message) {
|
|
1023
|
+
if (this.spinnerDialog != null) {
|
|
1024
|
+
this.spinnerDialog.dismiss();
|
|
1025
|
+
this.spinnerDialog = null;
|
|
1026
|
+
}
|
|
1027
|
+
final DroidGap me = this;
|
|
1028
|
+
this.spinnerDialog = ProgressDialog.show(DroidGap.this, title , message, true, true,
|
|
1029
|
+
new DialogInterface.OnCancelListener() {
|
|
1030
|
+
public void onCancel(DialogInterface dialog) {
|
|
1031
|
+
me.spinnerDialog = null;
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* Stop spinner.
|
|
1038
|
+
*/
|
|
1039
|
+
public void spinnerStop() {
|
|
1040
|
+
if (this.spinnerDialog != null) {
|
|
1041
|
+
this.spinnerDialog.dismiss();
|
|
1042
|
+
this.spinnerDialog = null;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* End this activity by calling finish for activity
|
|
1048
|
+
*/
|
|
1049
|
+
public void endActivity() {
|
|
1050
|
+
this.activityState = ACTIVITY_EXITING;
|
|
1051
|
+
this.finish();
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* Called when a key is pressed.
|
|
1056
|
+
*
|
|
1057
|
+
* @param keyCode
|
|
1058
|
+
* @param event
|
|
1059
|
+
*/
|
|
1060
|
+
@Override
|
|
1061
|
+
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
1062
|
+
if (this.appView == null) {
|
|
1063
|
+
return super.onKeyDown(keyCode, event);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
// If back key
|
|
1067
|
+
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
|
1068
|
+
|
|
1069
|
+
// If back key is bound, then send event to JavaScript
|
|
1070
|
+
if (this.bound) {
|
|
1071
|
+
this.appView.loadUrl("javascript:require('cordova').fireDocumentEvent('backbutton');");
|
|
1072
|
+
return true;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// If not bound
|
|
1076
|
+
else {
|
|
1077
|
+
|
|
1078
|
+
// Go to previous page in webview if it is possible to go back
|
|
1079
|
+
if (this.backHistory()) {
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// If not, then invoke behavior of super class
|
|
1084
|
+
else {
|
|
1085
|
+
this.activityState = ACTIVITY_EXITING;
|
|
1086
|
+
return super.onKeyDown(keyCode, event);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
// If menu key
|
|
1092
|
+
else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
|
1093
|
+
this.appView.loadUrl("javascript:require('cordova').fireDocumentEvent('menubutton');");
|
|
1094
|
+
return super.onKeyDown(keyCode, event);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// If search key
|
|
1098
|
+
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
|
|
1099
|
+
this.appView.loadUrl("javascript:require('cordova').fireDocumentEvent('searchbutton');");
|
|
1100
|
+
return true;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
return false;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Any calls to Activity.startActivityForResult must use method below, so
|
|
1108
|
+
* the result can be routed to them correctly.
|
|
1109
|
+
*
|
|
1110
|
+
* This is done to eliminate the need to modify DroidGap.java to receive activity results.
|
|
1111
|
+
*
|
|
1112
|
+
* @param intent The intent to start
|
|
1113
|
+
* @param requestCode Identifies who to send the result to
|
|
1114
|
+
*
|
|
1115
|
+
* @throws RuntimeException
|
|
1116
|
+
*/
|
|
1117
|
+
@Override
|
|
1118
|
+
public void startActivityForResult(Intent intent, int requestCode) throws RuntimeException {
|
|
1119
|
+
LOG.d(TAG, "DroidGap.startActivityForResult(intent,%d)", requestCode);
|
|
1120
|
+
super.startActivityForResult(intent, requestCode);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Launch an activity for which you would like a result when it finished. When this activity exits,
|
|
1125
|
+
* your onActivityResult() method will be called.
|
|
1126
|
+
*
|
|
1127
|
+
* @param command The command object
|
|
1128
|
+
* @param intent The intent to start
|
|
1129
|
+
* @param requestCode The request code that is passed to callback to identify the activity
|
|
1130
|
+
*/
|
|
1131
|
+
public void startActivityForResult(IPlugin command, Intent intent, int requestCode) {
|
|
1132
|
+
this.activityResultCallback = command;
|
|
1133
|
+
this.activityResultKeepRunning = this.keepRunning;
|
|
1134
|
+
|
|
1135
|
+
// If multitasking turned on, then disable it for activities that return results
|
|
1136
|
+
if (command != null) {
|
|
1137
|
+
this.keepRunning = false;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
// Start activity
|
|
1141
|
+
super.startActivityForResult(intent, requestCode);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
@Override
|
|
1145
|
+
/**
|
|
1146
|
+
* Called when an activity you launched exits, giving you the requestCode you started it with,
|
|
1147
|
+
* the resultCode it returned, and any additional data from it.
|
|
1148
|
+
*
|
|
1149
|
+
* @param requestCode The request code originally supplied to startActivityForResult(),
|
|
1150
|
+
* allowing you to identify who this result came from.
|
|
1151
|
+
* @param resultCode The integer result code returned by the child activity through its setResult().
|
|
1152
|
+
* @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
|
|
1153
|
+
*/
|
|
1154
|
+
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
|
1155
|
+
super.onActivityResult(requestCode, resultCode, intent);
|
|
1156
|
+
IPlugin callback = this.activityResultCallback;
|
|
1157
|
+
if (callback != null) {
|
|
1158
|
+
callback.onActivityResult(requestCode, resultCode, intent);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
public void setActivityResultCallback(IPlugin plugin) {
|
|
1163
|
+
this.activityResultCallback = plugin;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
|
|
1168
|
+
* The errorCode parameter corresponds to one of the ERROR_* constants.
|
|
1169
|
+
*
|
|
1170
|
+
* @param errorCode The error code corresponding to an ERROR_* value.
|
|
1171
|
+
* @param description A String describing the error.
|
|
1172
|
+
* @param failingUrl The url that failed to load.
|
|
1173
|
+
*/
|
|
1174
|
+
public void onReceivedError(final int errorCode, final String description, final String failingUrl) {
|
|
1175
|
+
final DroidGap me = this;
|
|
1176
|
+
|
|
1177
|
+
// If errorUrl specified, then load it
|
|
1178
|
+
final String errorUrl = me.getStringProperty("errorUrl", null);
|
|
1179
|
+
if ((errorUrl != null) && (errorUrl.startsWith("file://") || errorUrl.indexOf(me.baseUrl) == 0 || isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
|
|
1180
|
+
|
|
1181
|
+
// Load URL on UI thread
|
|
1182
|
+
me.runOnUiThread(new Runnable() {
|
|
1183
|
+
public void run() {
|
|
1184
|
+
me.showWebPage(errorUrl, false, true, null);
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// If not, then display error dialog
|
|
1190
|
+
else {
|
|
1191
|
+
me.runOnUiThread(new Runnable() {
|
|
1192
|
+
public void run() {
|
|
1193
|
+
me.appView.setVisibility(View.GONE);
|
|
1194
|
+
me.displayError("Application Error", description + " ("+failingUrl+")", "OK", true);
|
|
1195
|
+
}
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
/**
|
|
1201
|
+
* Display an error dialog and optionally exit application.
|
|
1202
|
+
*
|
|
1203
|
+
* @param title
|
|
1204
|
+
* @param message
|
|
1205
|
+
* @param button
|
|
1206
|
+
* @param exit
|
|
1207
|
+
*/
|
|
1208
|
+
public void displayError(final String title, final String message, final String button, final boolean exit) {
|
|
1209
|
+
final DroidGap me = this;
|
|
1210
|
+
me.runOnUiThread(new Runnable() {
|
|
1211
|
+
public void run() {
|
|
1212
|
+
AlertDialog.Builder dlg = new AlertDialog.Builder(me);
|
|
1213
|
+
dlg.setMessage(message);
|
|
1214
|
+
dlg.setTitle(title);
|
|
1215
|
+
dlg.setCancelable(false);
|
|
1216
|
+
dlg.setPositiveButton(button,
|
|
1217
|
+
new AlertDialog.OnClickListener() {
|
|
1218
|
+
public void onClick(DialogInterface dialog, int which) {
|
|
1219
|
+
dialog.dismiss();
|
|
1220
|
+
if (exit) {
|
|
1221
|
+
me.endActivity();
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1225
|
+
dlg.create();
|
|
1226
|
+
dlg.show();
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* Load Cordova configuration from res/xml/cordova.xml.
|
|
1234
|
+
* Approved list of URLs that can be loaded into DroidGap
|
|
1235
|
+
* <access origin="http://server regexp" subdomains="true" />
|
|
1236
|
+
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
|
|
1237
|
+
* <log level="DEBUG" />
|
|
1238
|
+
*/
|
|
1239
|
+
private void loadConfiguration() {
|
|
1240
|
+
int id = getResources().getIdentifier("cordova", "xml", getPackageName());
|
|
1241
|
+
if (id == 0) {
|
|
1242
|
+
LOG.i("CordovaLog", "cordova.xml missing. Ignoring...");
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
XmlResourceParser xml = getResources().getXml(id);
|
|
1246
|
+
int eventType = -1;
|
|
1247
|
+
while (eventType != XmlResourceParser.END_DOCUMENT) {
|
|
1248
|
+
if (eventType == XmlResourceParser.START_TAG) {
|
|
1249
|
+
String strNode = xml.getName();
|
|
1250
|
+
if (strNode.equals("access")) {
|
|
1251
|
+
String origin = xml.getAttributeValue(null, "origin");
|
|
1252
|
+
String subdomains = xml.getAttributeValue(null, "subdomains");
|
|
1253
|
+
if (origin != null) {
|
|
1254
|
+
this.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
else if (strNode.equals("log")) {
|
|
1258
|
+
String level = xml.getAttributeValue(null, "level");
|
|
1259
|
+
LOG.i("CordovaLog", "Found log level %s", level);
|
|
1260
|
+
if (level != null) {
|
|
1261
|
+
LOG.setLogLevel(level);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
else if (strNode.equals("preference")) {
|
|
1265
|
+
String name = xml.getAttributeValue(null, "name");
|
|
1266
|
+
String value = xml.getAttributeValue(null, "value");
|
|
1267
|
+
String readonlyString = xml.getAttributeValue(null, "readonly");
|
|
1268
|
+
|
|
1269
|
+
boolean readonly = (readonlyString != null &&
|
|
1270
|
+
readonlyString.equals("true"));
|
|
1271
|
+
|
|
1272
|
+
LOG.i("CordovaLog", "Found preference for %s", name);
|
|
1273
|
+
|
|
1274
|
+
preferences.add(new PreferenceNode(name, value, readonly));
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
try {
|
|
1278
|
+
eventType = xml.next();
|
|
1279
|
+
} catch (XmlPullParserException e) {
|
|
1280
|
+
e.printStackTrace();
|
|
1281
|
+
} catch (IOException e) {
|
|
1282
|
+
e.printStackTrace();
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/**
|
|
1288
|
+
* Add entry to approved list of URLs (whitelist)
|
|
1289
|
+
*
|
|
1290
|
+
* @param origin URL regular expression to allow
|
|
1291
|
+
* @param subdomains T=include all subdomains under origin
|
|
1292
|
+
*/
|
|
1293
|
+
private void addWhiteListEntry(String origin, boolean subdomains) {
|
|
1294
|
+
try {
|
|
1295
|
+
// Unlimited access to network resources
|
|
1296
|
+
if(origin.compareTo("*") == 0) {
|
|
1297
|
+
LOG.d(TAG, "Unlimited access to network resources");
|
|
1298
|
+
whiteList.add(Pattern.compile(".*"));
|
|
1299
|
+
} else { // specific access
|
|
1300
|
+
// check if subdomains should be included
|
|
1301
|
+
// TODO: we should not add more domains if * has already been added
|
|
1302
|
+
if (subdomains) {
|
|
1303
|
+
// XXX making it stupid friendly for people who forget to include protocol/SSL
|
|
1304
|
+
if(origin.startsWith("http")) {
|
|
1305
|
+
whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?")));
|
|
1306
|
+
} else {
|
|
1307
|
+
whiteList.add(Pattern.compile("^https?://(.*\\.)?"+origin));
|
|
1308
|
+
}
|
|
1309
|
+
LOG.d(TAG, "Origin to allow with subdomains: %s", origin);
|
|
1310
|
+
} else {
|
|
1311
|
+
// XXX making it stupid friendly for people who forget to include protocol/SSL
|
|
1312
|
+
if(origin.startsWith("http")) {
|
|
1313
|
+
whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://")));
|
|
1314
|
+
} else {
|
|
1315
|
+
whiteList.add(Pattern.compile("^https?://"+origin));
|
|
1316
|
+
}
|
|
1317
|
+
LOG.d(TAG, "Origin to allow: %s", origin);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
} catch(Exception e) {
|
|
1321
|
+
LOG.d(TAG, "Failed to add origin %s", origin);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Determine if URL is in approved list of URLs to load.
|
|
1327
|
+
*
|
|
1328
|
+
* @param url
|
|
1329
|
+
* @return
|
|
1330
|
+
*/
|
|
1331
|
+
boolean isUrlWhiteListed(String url) {
|
|
1332
|
+
|
|
1333
|
+
// Check to see if we have matched url previously
|
|
1334
|
+
if (whiteListCache.get(url) != null) {
|
|
1335
|
+
return true;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// Look for match in white list
|
|
1339
|
+
Iterator<Pattern> pit = whiteList.iterator();
|
|
1340
|
+
while (pit.hasNext()) {
|
|
1341
|
+
Pattern p = pit.next();
|
|
1342
|
+
Matcher m = p.matcher(url);
|
|
1343
|
+
|
|
1344
|
+
// If match found, then cache it to speed up subsequent comparisons
|
|
1345
|
+
if (m.find()) {
|
|
1346
|
+
whiteListCache.put(url, true);
|
|
1347
|
+
return true;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
return false;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/*
|
|
1354
|
+
* URL stack manipulators
|
|
1355
|
+
*/
|
|
1356
|
+
|
|
1357
|
+
/**
|
|
1358
|
+
* Returns the top url on the stack without removing it from
|
|
1359
|
+
* the stack.
|
|
1360
|
+
*/
|
|
1361
|
+
public String peekAtUrlStack() {
|
|
1362
|
+
if (urls.size() > 0) {
|
|
1363
|
+
return urls.peek();
|
|
1364
|
+
}
|
|
1365
|
+
return "";
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Add a url to the stack
|
|
1370
|
+
*
|
|
1371
|
+
* @param url
|
|
1372
|
+
*/
|
|
1373
|
+
public void pushUrl(String url) {
|
|
1374
|
+
urls.push(url);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/*
|
|
1378
|
+
* Hook in DroidGap for menu plugins
|
|
1379
|
+
*
|
|
1380
|
+
*/
|
|
1381
|
+
|
|
1382
|
+
@Override
|
|
1383
|
+
public boolean onCreateOptionsMenu(Menu menu)
|
|
1384
|
+
{
|
|
1385
|
+
this.postMessage("onCreateOptionsMenu", menu);
|
|
1386
|
+
return super.onCreateOptionsMenu(menu);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
@Override
|
|
1390
|
+
public boolean onPrepareOptionsMenu(Menu menu)
|
|
1391
|
+
{
|
|
1392
|
+
this.postMessage("onPrepareOptionsMenu", menu);
|
|
1393
|
+
return super.onPrepareOptionsMenu(menu);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
@Override
|
|
1397
|
+
public boolean onOptionsItemSelected(MenuItem item)
|
|
1398
|
+
{
|
|
1399
|
+
this.postMessage("onOptionsItemSelected", item);
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
public Context getContext() {
|
|
1404
|
+
return this;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
public void bindBackButton(boolean override) {
|
|
1408
|
+
// TODO Auto-generated method stub
|
|
1409
|
+
this.bound = override;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
public boolean isBackButtonBound() {
|
|
1413
|
+
// TODO Auto-generated method stub
|
|
1414
|
+
return this.bound;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
}
|