calatrava 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/.rvmrc +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +202 -0
- data/Plans.md +20 -0
- data/README.md +73 -0
- data/Rakefile +26 -0
- data/bin/calatrava +6 -0
- data/calatrava.gemspec +35 -0
- data/features/cli.feature +14 -0
- data/features/project.feature +48 -0
- data/features/step_definitions/template_steps.rb +8 -0
- data/features/support/env.rb +5 -0
- data/lib/calatrava/app.rb +30 -0
- data/lib/calatrava/manifest.rb +44 -0
- data/lib/calatrava/project.rb +218 -0
- data/lib/calatrava/resources_build_phase.rb +19 -0
- data/lib/calatrava/tasks/apache.rb +44 -0
- data/lib/calatrava/tasks/artifact.rb +24 -0
- data/lib/calatrava/tasks/assets.rb +6 -0
- data/lib/calatrava/tasks/automation.rb +38 -0
- data/lib/calatrava/tasks/bootstrap.rb +10 -0
- data/lib/calatrava/tasks/build.rb +1 -0
- data/lib/calatrava/tasks/configuration.rb +41 -0
- data/lib/calatrava/tasks/droid.rb +83 -0
- data/lib/calatrava/tasks/haml.rb +71 -0
- data/lib/calatrava/tasks/ios.rb +73 -0
- data/lib/calatrava/tasks/kernel.rb +52 -0
- data/lib/calatrava/tasks/precommit.rb +22 -0
- data/lib/calatrava/tasks/release.rb +17 -0
- data/lib/calatrava/tasks/shell.rb +17 -0
- data/lib/calatrava/tasks/web.rb +82 -0
- data/lib/calatrava/tasks.rb +93 -0
- data/lib/calatrava/template.rb +44 -0
- data/lib/calatrava/templates/.rvmrc.calatrava +2 -0
- data/lib/calatrava/templates/Gemfile.calatrava +4 -0
- data/lib/calatrava/templates/Rakefile +1 -0
- data/lib/calatrava/templates/assets/lib/ICanHaz.js +542 -0
- data/lib/calatrava/templates/assets/lib/underscore.js +1059 -0
- data/lib/calatrava/templates/assets/lib/zepto.js +1355 -0
- data/lib/calatrava/templates/build_env.sh +2 -0
- data/lib/calatrava/templates/config/environments.yml +17 -0
- data/lib/calatrava/templates/config/templates/env.coffee.erb +7 -0
- data/lib/calatrava/templates/config/templates/httpd.conf.erb +33 -0
- data/lib/calatrava/templates/droid/app/bridge.coffee +130 -0
- data/lib/calatrava/templates/droid/calatrava/ant/calatrava.xml +48 -0
- data/lib/calatrava/templates/droid/calatrava/calatrava-build.xml +91 -0
- data/lib/calatrava/templates/droid/calatrava/ivy.xml +8 -0
- data/lib/calatrava/templates/droid/calatrava/ivysettings.xml +12 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/AndroidManifest.xml.calatrava +20 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/ConversionForm.java.calatrava +27 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/CALATRAVA_TMPL/Title.java.calatrava +23 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/CalatravaPage.java +13 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AjaxRequestManager.java +166 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/AssetRepository.java +17 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/KernelBridge.java +25 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/Launcher.java +85 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/PageRegistry.java +225 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RegisteredActivity.java +86 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RequestLoader.java +31 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/bridge/RhinoService.java +212 -0
- data/lib/calatrava/templates/droid/calatrava/src/com/calatrava/shell/WebViewActivity.java +247 -0
- data/lib/calatrava/templates/droid/manifest.yml +1 -0
- data/lib/calatrava/templates/ios/Podfile.calatrava +5 -0
- data/lib/calatrava/templates/ios/manifest.yml +1 -0
- data/lib/calatrava/templates/ios/res/js/bridge.js +249 -0
- data/lib/calatrava/templates/ios/res/xibs/ProgressViewController.xib +334 -0
- data/lib/calatrava/templates/ios/res/xibs/WebViewController.xib +173 -0
- data/lib/calatrava/templates/ios/src/AppDelegate.h +8 -0
- data/lib/calatrava/templates/ios/src/AppDelegate.m +56 -0
- data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Info.plist +45 -0
- data/lib/calatrava/templates/ios/src/CALATRAVA_TMPL-Prefix.pch +14 -0
- data/lib/calatrava/templates/ios/src/ConversionFormViewController.h +16 -0
- data/lib/calatrava/templates/ios/src/ConversionFormViewController.m +179 -0
- data/lib/calatrava/templates/ios/src/ConversionFormViewController.xib +357 -0
- data/lib/calatrava/templates/ios/src/en.lproj/InfoPlist.strings +2 -0
- data/lib/calatrava/templates/ios/src/main.m +10 -0
- data/lib/calatrava/templates/ios/test/AJAXConnectionTest.m +21 -0
- data/lib/calatrava/templates/ios/test/AppTests-Prefix.pch +8 -0
- data/lib/calatrava/templates/ios/test/CalatravaiOSTests-Info.plist +22 -0
- data/lib/calatrava/templates/ios/test/TWBridgePageRegistryTest.m +15 -0
- data/lib/calatrava/templates/ios/test/en.lproj/InfoPlist.strings +2 -0
- data/lib/calatrava/templates/kernel/.gitignore +1 -0
- data/lib/calatrava/templates/kernel/app/calatrava.coffee +8 -0
- data/lib/calatrava/templates/kernel/app/converter/controller.converter.coffee +50 -0
- data/lib/calatrava/templates/kernel/app/converter/init.converter.coffee +11 -0
- data/lib/calatrava/templates/kernel/app/pageHelper.coffee +17 -0
- data/lib/calatrava/templates/kernel/features/support/bridge.coffee +124 -0
- data/lib/calatrava/templates/kernel/features/support/spec_helper.js +49 -0
- data/lib/calatrava/templates/kernel/spec/converter/controller.converter.spec.coffee +37 -0
- data/lib/calatrava/templates/kernel/spec/environment.spec_helper.coffee +25 -0
- data/lib/calatrava/templates/kernel/spec/spec_helper.js +49 -0
- data/lib/calatrava/templates/kernel/spec/stubView.coffee +18 -0
- data/lib/calatrava/templates/kernel/watchr.rb +17 -0
- data/lib/calatrava/templates/package.json +20 -0
- data/lib/calatrava/templates/shell/layouts/single_page.haml +23 -0
- data/lib/calatrava/templates/shell/pages/converter/conversionForm.haml +12 -0
- data/lib/calatrava/templates/shell/pages/converter/page.conversionForm.coffee +42 -0
- data/lib/calatrava/templates/shell/shell.scss +1 -0
- data/lib/calatrava/templates/shell/support/shell.coffee +21 -0
- data/lib/calatrava/templates/web/apache/conf/mime.types +1357 -0
- data/lib/calatrava/templates/web/app/source/bridge.coffee +158 -0
- data/lib/calatrava/templates/web/app/source/init.coffee +14 -0
- data/lib/calatrava/templates/web/app/views/index.haml +18 -0
- data/lib/calatrava/templates/web/deploy/instance.sh +10 -0
- data/lib/calatrava/templates/web/manifest.yml +1 -0
- data/lib/calatrava/version.rb +3 -0
- data/lib/calatrava.rb +5 -0
- metadata +302 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
package com.calatrava.bridge;
|
2
|
+
|
3
|
+
import android.app.Application;
|
4
|
+
import android.content.ComponentName;
|
5
|
+
import android.content.Context;
|
6
|
+
import android.content.Intent;
|
7
|
+
import android.content.ServiceConnection;
|
8
|
+
import android.os.IBinder;
|
9
|
+
import android.util.Log;
|
10
|
+
|
11
|
+
import java.io.IOException;
|
12
|
+
import java.io.BufferedReader;
|
13
|
+
import java.io.InputStreamReader;
|
14
|
+
|
15
|
+
public class Launcher {
|
16
|
+
private static String TAG = Launcher.class.getSimpleName();
|
17
|
+
|
18
|
+
private static String appName;
|
19
|
+
private static RhinoService rhino;
|
20
|
+
private static Context appContext;
|
21
|
+
private static Application application;
|
22
|
+
private static Runnable startUp;
|
23
|
+
|
24
|
+
static ServiceConnection connection = new ServiceConnection() {
|
25
|
+
public void onServiceConnected(ComponentName componentName, IBinder iBinder)
|
26
|
+
{
|
27
|
+
try
|
28
|
+
{
|
29
|
+
rhino = ((RhinoService.LocalBinder) iBinder).getService();
|
30
|
+
PageRegistry.setSharedRegistry(new PageRegistry(appName, appContext, application, rhino));
|
31
|
+
AjaxRequestManager.setSharedManager(new AjaxRequestManager(appContext, rhino));
|
32
|
+
initBridge();
|
33
|
+
startUp.run();
|
34
|
+
}
|
35
|
+
catch (Exception e)
|
36
|
+
{
|
37
|
+
Log.e(TAG, "Unable to start.", e);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
public void onServiceDisconnected(ComponentName componentName) {
|
42
|
+
|
43
|
+
}
|
44
|
+
};
|
45
|
+
|
46
|
+
public static void launchKernel(String appName,
|
47
|
+
Context appContext,
|
48
|
+
Application application,
|
49
|
+
Runnable startUp) {
|
50
|
+
Launcher.appName = appName;
|
51
|
+
Launcher.appContext = appContext;
|
52
|
+
Launcher.application = application;
|
53
|
+
Launcher.startUp = startUp;
|
54
|
+
|
55
|
+
Intent serviceIntent = new Intent(appContext, RhinoService.class);
|
56
|
+
appContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
|
57
|
+
}
|
58
|
+
|
59
|
+
public static void launchFlow(String flow)
|
60
|
+
{
|
61
|
+
rhino.callJsFunction(flow);
|
62
|
+
}
|
63
|
+
|
64
|
+
private static void initBridge() {
|
65
|
+
AssetRepository assets = new AssetRepository(appContext);
|
66
|
+
|
67
|
+
try {
|
68
|
+
Log.d(TAG, "About to prep the rhino");
|
69
|
+
rhino.initRhino();
|
70
|
+
|
71
|
+
Log.d(TAG, "About to load and start kernel");
|
72
|
+
// Load all the application JS
|
73
|
+
KernelBridge bridge = new KernelBridge(assets, rhino);
|
74
|
+
BufferedReader loadFileReader = new BufferedReader(new InputStreamReader(appContext.getAssets().open("hybrid/load_file.text")), 8192);
|
75
|
+
String line = null;
|
76
|
+
while ((line = loadFileReader.readLine()) != null)
|
77
|
+
{
|
78
|
+
bridge.loadLibrary(line);
|
79
|
+
}
|
80
|
+
|
81
|
+
} catch (IOException e) {
|
82
|
+
Log.d(TAG, "LauncherActivity failed to start: " + e);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
@@ -0,0 +1,225 @@
|
|
1
|
+
package com.calatrava.bridge;
|
2
|
+
|
3
|
+
import android.app.Application;
|
4
|
+
import android.content.Context;
|
5
|
+
import android.content.Intent;
|
6
|
+
import android.content.ContextWrapper;
|
7
|
+
import android.net.Uri;
|
8
|
+
import android.util.Log;
|
9
|
+
import android.content.pm.PackageManager.NameNotFoundException;
|
10
|
+
|
11
|
+
import org.mozilla.javascript.ScriptableObject;
|
12
|
+
|
13
|
+
import com.calatrava.CalatravaPage;
|
14
|
+
|
15
|
+
import java.util.*;
|
16
|
+
|
17
|
+
import java.io.IOException;
|
18
|
+
import java.net.URISyntaxException;
|
19
|
+
|
20
|
+
import dalvik.system.DexFile;
|
21
|
+
import dalvik.system.PathClassLoader;
|
22
|
+
import dalvik.system.DexClassLoader;
|
23
|
+
|
24
|
+
import java.lang.annotation.Annotation;
|
25
|
+
|
26
|
+
public class PageRegistry {
|
27
|
+
public static String TAG = PageRegistry.class.getSimpleName();
|
28
|
+
private static PageRegistry sharedRegistry;
|
29
|
+
|
30
|
+
private Context appContext;
|
31
|
+
private RhinoService rhino;
|
32
|
+
private Map<String, Class<?>> pageFactories = new HashMap<String, Class<?>>();
|
33
|
+
private Map<String, RegisteredPage> registeredPages = new HashMap<String, RegisteredPage>();
|
34
|
+
|
35
|
+
public static PageRegistry sharedRegistry() {
|
36
|
+
return sharedRegistry;
|
37
|
+
}
|
38
|
+
|
39
|
+
public static void setSharedRegistry(PageRegistry shared) {
|
40
|
+
Log.d(TAG, "Set shared page registry");
|
41
|
+
sharedRegistry = shared;
|
42
|
+
}
|
43
|
+
|
44
|
+
public PageRegistry(String appName, Context appContext, Application app, RhinoService rhino)
|
45
|
+
throws IOException, URISyntaxException, ClassNotFoundException, NameNotFoundException
|
46
|
+
{
|
47
|
+
this.appContext = appContext;
|
48
|
+
this.rhino = rhino;
|
49
|
+
|
50
|
+
// Find all the logical page classes in the app
|
51
|
+
Log.d(TAG, "Searching for Calatrava pages in '" + appName + "'");
|
52
|
+
addPages(appName, appContext);
|
53
|
+
}
|
54
|
+
|
55
|
+
private void addPages(String packageName, Context context)
|
56
|
+
throws IOException, URISyntaxException, ClassNotFoundException, NameNotFoundException
|
57
|
+
{
|
58
|
+
String apkName = context.getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
|
59
|
+
DexFile dexFile = new DexFile(apkName);
|
60
|
+
PathClassLoader classLoader2 = new PathClassLoader(apkName, Thread.currentThread().getContextClassLoader());
|
61
|
+
DexClassLoader classLoader = new DexClassLoader(apkName, new ContextWrapper(context).getCacheDir().getAbsolutePath(), null, classLoader2);
|
62
|
+
|
63
|
+
Enumeration<String> entries = dexFile.entries();
|
64
|
+
while (entries.hasMoreElements())
|
65
|
+
{
|
66
|
+
String entry = entries.nextElement();
|
67
|
+
// only check items that exist in source package and not in libraries, etc.
|
68
|
+
if (entry.startsWith(packageName))
|
69
|
+
{
|
70
|
+
Class<?> entryClass = classLoader.loadClass(entry);
|
71
|
+
if (entryClass != null)
|
72
|
+
{
|
73
|
+
Annotation[] annotations = entryClass.getAnnotations();
|
74
|
+
for (Annotation annotation : annotations)
|
75
|
+
{
|
76
|
+
if (annotation instanceof CalatravaPage)
|
77
|
+
{
|
78
|
+
String pageName = ((CalatravaPage)annotation).name();
|
79
|
+
Log.d(TAG, "Registering Calatrava page: " + pageName);
|
80
|
+
pageFactories.put(pageName, entryClass);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
public void changePage(String target) {
|
89
|
+
Log.d(TAG, "changePage('" + target + "')");
|
90
|
+
Class activityClass = pageFactories.get(target);
|
91
|
+
Log.d(TAG, "Activity to be started: " + activityClass.getSimpleName());
|
92
|
+
appContext.startActivity(new Intent(appContext, activityClass));
|
93
|
+
}
|
94
|
+
|
95
|
+
public void displayWidget(String name, String options) {
|
96
|
+
appContext.sendBroadcast(new Intent("com.calatrava.widget").putExtra("name", name).putExtra("options", options));
|
97
|
+
}
|
98
|
+
|
99
|
+
public void displayDialog(String dialogName) {
|
100
|
+
appContext.sendBroadcast(new Intent("com.calatrava.dialog").putExtra("name", dialogName));
|
101
|
+
}
|
102
|
+
|
103
|
+
public void alert(String message) {
|
104
|
+
Log.d(TAG, "Broadcasting alert message: '" + message + "'");
|
105
|
+
appContext.sendBroadcast(new Intent("com.calatrava.alert").putExtra("message", message));
|
106
|
+
}
|
107
|
+
|
108
|
+
public void openUrl(String url) {
|
109
|
+
Intent browser = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
110
|
+
appContext.startActivity(browser);
|
111
|
+
}
|
112
|
+
|
113
|
+
public void track(String pageName, String channel, String eventName, Object variables, Object properties) {
|
114
|
+
}
|
115
|
+
|
116
|
+
public void startTimer(int timeout, final String timerId) {
|
117
|
+
final Timer timer = new Timer();
|
118
|
+
timer.schedule(new TimerTask() {
|
119
|
+
@Override
|
120
|
+
public void run() {
|
121
|
+
timer.cancel();
|
122
|
+
timer.purge();
|
123
|
+
rhino.callJsFunction("tw.bridge.timers.fireTimer", new String[] {timerId});
|
124
|
+
}
|
125
|
+
}, 1000 * timeout);
|
126
|
+
}
|
127
|
+
|
128
|
+
private HashMap<String, String> jsObjectToMap(ScriptableObject obj) {
|
129
|
+
HashMap<String, String> map = new HashMap<String, String>();
|
130
|
+
for (Object k : obj.getIds()) {
|
131
|
+
if (k instanceof String) {
|
132
|
+
map.put((String) k, ScriptableObject.getProperty(obj, (String) k).toString());
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return map;
|
136
|
+
}
|
137
|
+
|
138
|
+
private void ensureRegisteredPage(String name, RegisteredActivity page) {
|
139
|
+
if (registeredPages.get(name) == null) {
|
140
|
+
registeredPages.put(name, new RegisteredPage(page));
|
141
|
+
} else if (page != null) {
|
142
|
+
registeredPages.get(name).setPage(page);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
public void registerPage(String name, RegisteredActivity page) {
|
147
|
+
ensureRegisteredPage(name, page);
|
148
|
+
}
|
149
|
+
|
150
|
+
public void unregisterPage(String pageName) {
|
151
|
+
registeredPages.remove(pageName);
|
152
|
+
}
|
153
|
+
|
154
|
+
public String getValueForField(String page, String field) {
|
155
|
+
Log.d(TAG, "Requesting field '" + field + "' from page '" + page + "'");
|
156
|
+
ensureRegisteredPage(page, null);
|
157
|
+
return registeredPages.get(page).getFieldValue(field);
|
158
|
+
}
|
159
|
+
|
160
|
+
public void renderPage(String page, String renderJson) {
|
161
|
+
Log.d(TAG, "renderPage: '" + page + "' Response object: " + renderJson);
|
162
|
+
|
163
|
+
ensureRegisteredPage(page, null);
|
164
|
+
registeredPages.get(page).render(renderJson);
|
165
|
+
}
|
166
|
+
|
167
|
+
public void pageOffscreen(String page) {
|
168
|
+
ensureRegisteredPage(page, null);
|
169
|
+
registeredPages.get(page).pageOffscreen();
|
170
|
+
}
|
171
|
+
|
172
|
+
public void pageOnscreen(String page) {
|
173
|
+
ensureRegisteredPage(page, null);
|
174
|
+
registeredPages.get(page).pageOnscreen();
|
175
|
+
}
|
176
|
+
|
177
|
+
private class RegisteredPage {
|
178
|
+
private RegisteredActivity activity;
|
179
|
+
List<String> pendingRenders = new ArrayList<String>();
|
180
|
+
boolean onScreen = false;
|
181
|
+
|
182
|
+
private RegisteredPage(RegisteredActivity activity) {
|
183
|
+
this.activity = activity;
|
184
|
+
}
|
185
|
+
|
186
|
+
public RegisteredActivity getPage() {
|
187
|
+
return activity;
|
188
|
+
}
|
189
|
+
|
190
|
+
public void setPage(RegisteredActivity page) {
|
191
|
+
this.activity = page;
|
192
|
+
}
|
193
|
+
|
194
|
+
public void render(String renderJson) {
|
195
|
+
if (activity != null && onScreen) {
|
196
|
+
activity.render(renderJson);
|
197
|
+
} else {
|
198
|
+
pendingRenders.add(renderJson);
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
public String getFieldValue(String field) {
|
203
|
+
if (activity != null) {
|
204
|
+
return activity.getFieldValue(field);
|
205
|
+
} else {
|
206
|
+
return "";
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
public void pageOffscreen() {
|
211
|
+
onScreen = false;
|
212
|
+
}
|
213
|
+
|
214
|
+
public void pageOnscreen() {
|
215
|
+
onScreen = true;
|
216
|
+
|
217
|
+
for (String pendingRender : pendingRenders) {
|
218
|
+
Log.d(TAG, "Pending activity for: " + pendingRender);
|
219
|
+
|
220
|
+
activity.render(pendingRender);
|
221
|
+
}
|
222
|
+
pendingRenders.clear();
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
package com.calatrava.bridge;
|
2
|
+
|
3
|
+
import android.app.Activity;
|
4
|
+
import android.app.AlertDialog;
|
5
|
+
import android.content.*;
|
6
|
+
import android.os.Bundle;
|
7
|
+
import android.os.IBinder;
|
8
|
+
import android.util.Log;
|
9
|
+
|
10
|
+
public abstract class RegisteredActivity extends Activity {
|
11
|
+
private String TAG = RegisteredActivity.class.getSimpleName();
|
12
|
+
|
13
|
+
private RhinoService rhino;
|
14
|
+
private RequestLoader spinner = new RequestLoader(this);
|
15
|
+
private ServiceConnection connection = new ServiceConnection() {
|
16
|
+
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
|
17
|
+
rhino = ((RhinoService.LocalBinder) iBinder).getService();
|
18
|
+
RegisteredActivity.this.onRhinoConnected(rhino);
|
19
|
+
}
|
20
|
+
|
21
|
+
public void onServiceDisconnected(ComponentName componentName) {
|
22
|
+
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
27
|
+
@Override
|
28
|
+
public void onReceive(Context context, Intent intent) {
|
29
|
+
Log.d(TAG, "Received broadcast");
|
30
|
+
if (intent.getAction().endsWith("start")) {
|
31
|
+
spinner.onLoadingStart();
|
32
|
+
} else if (intent.getAction().endsWith("finish")) {
|
33
|
+
spinner.onLoadingFinish();
|
34
|
+
} else {
|
35
|
+
AlertDialog.Builder builder = new AlertDialog.Builder(RegisteredActivity.this);
|
36
|
+
builder.setMessage(intent.getExtras().getString("message"))
|
37
|
+
.setCancelable(false)
|
38
|
+
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
39
|
+
@Override
|
40
|
+
public void onClick(DialogInterface dialogInterface, int i) {
|
41
|
+
dialogInterface.dismiss();
|
42
|
+
}
|
43
|
+
});
|
44
|
+
AlertDialog dialog = builder.create();
|
45
|
+
dialog.show();
|
46
|
+
}
|
47
|
+
}
|
48
|
+
};
|
49
|
+
|
50
|
+
@Override
|
51
|
+
protected void onCreate(Bundle availableData) {
|
52
|
+
super.onCreate(availableData);
|
53
|
+
Intent serviceIntent = new Intent(this, RhinoService.class);
|
54
|
+
bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
|
55
|
+
}
|
56
|
+
|
57
|
+
@Override
|
58
|
+
protected void onResume() {
|
59
|
+
super.onResume();
|
60
|
+
registerReceiver(receiver, new IntentFilter("com.calatrava.ajax.start"));
|
61
|
+
registerReceiver(receiver, new IntentFilter("com.calatrava.ajax.finish"));
|
62
|
+
registerReceiver(receiver, new IntentFilter("com.calatrava.alert"));
|
63
|
+
}
|
64
|
+
|
65
|
+
@Override
|
66
|
+
protected void onPause() {
|
67
|
+
super.onPause();
|
68
|
+
unregisterReceiver(receiver);
|
69
|
+
}
|
70
|
+
|
71
|
+
@Override
|
72
|
+
public void onDestroy() {
|
73
|
+
super.onDestroy();
|
74
|
+
unbindService(connection);
|
75
|
+
}
|
76
|
+
|
77
|
+
public void invokeWidgetCallback(String...args) {
|
78
|
+
rhino.callJsFunction("tw.bridge.widgets.invokeCallback", args);
|
79
|
+
}
|
80
|
+
|
81
|
+
protected abstract void onRhinoConnected(RhinoService rhino);
|
82
|
+
|
83
|
+
public abstract String getFieldValue(String field);
|
84
|
+
|
85
|
+
public abstract void render(final String json);
|
86
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
package com.calatrava.bridge;
|
2
|
+
|
3
|
+
import android.app.Activity;
|
4
|
+
import android.app.ActivityManager;
|
5
|
+
import android.app.ProgressDialog;
|
6
|
+
import android.content.Context;
|
7
|
+
import android.util.Log;
|
8
|
+
|
9
|
+
public class RequestLoader {
|
10
|
+
private String TAG = RequestLoader.class.getSimpleName();
|
11
|
+
|
12
|
+
private ProgressDialog dialog;
|
13
|
+
private Activity parent;
|
14
|
+
|
15
|
+
public RequestLoader(Activity parent) {
|
16
|
+
this.parent = parent;
|
17
|
+
}
|
18
|
+
|
19
|
+
public void onLoadingStart() {
|
20
|
+
Log.d(TAG, "About to create loader");
|
21
|
+
dialog = new ProgressDialog(parent);
|
22
|
+
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
23
|
+
dialog.setMessage("Loading...");
|
24
|
+
dialog.setCancelable(false);
|
25
|
+
dialog.show();
|
26
|
+
}
|
27
|
+
|
28
|
+
public void onLoadingFinish() {
|
29
|
+
dialog.hide();
|
30
|
+
}
|
31
|
+
}
|
@@ -0,0 +1,212 @@
|
|
1
|
+
package com.calatrava.bridge;
|
2
|
+
|
3
|
+
import android.app.Service;
|
4
|
+
import android.content.Intent;
|
5
|
+
import android.os.*;
|
6
|
+
import android.util.Log;
|
7
|
+
import org.mozilla.javascript.Context;
|
8
|
+
import org.mozilla.javascript.Scriptable;
|
9
|
+
import org.mozilla.javascript.ScriptableObject;
|
10
|
+
|
11
|
+
import java.io.IOException;
|
12
|
+
import java.io.Reader;
|
13
|
+
import java.lang.String;
|
14
|
+
import java.lang.ThreadGroup;
|
15
|
+
import java.util.concurrent.CountDownLatch;
|
16
|
+
|
17
|
+
public class RhinoService extends Service {
|
18
|
+
public static String TAG = RhinoService.class.getSimpleName();
|
19
|
+
|
20
|
+
private Scriptable mScope;
|
21
|
+
private JSEvalThread evaller = new JSEvalThread();
|
22
|
+
|
23
|
+
private final IBinder mBinder = new LocalBinder();
|
24
|
+
|
25
|
+
CountDownLatch countDownLatch = new CountDownLatch(1);
|
26
|
+
|
27
|
+
@Override
|
28
|
+
public IBinder onBind(Intent intent) {
|
29
|
+
return mBinder;
|
30
|
+
}
|
31
|
+
|
32
|
+
@Override
|
33
|
+
public void onCreate() {
|
34
|
+
super.onCreate();
|
35
|
+
Log.d(TAG, "RhinoService created.");
|
36
|
+
}
|
37
|
+
|
38
|
+
public void initRhino() {
|
39
|
+
Context ctxt = enterContext();
|
40
|
+
try {
|
41
|
+
mScope = ctxt.initStandardObjects();
|
42
|
+
|
43
|
+
Object wrappedRegistry = Context.javaToJS(PageRegistry.sharedRegistry(), mScope);
|
44
|
+
ScriptableObject.putProperty(mScope, "pageRegistry", wrappedRegistry);
|
45
|
+
|
46
|
+
Object wrappedAjaxRequestManagerRegistry = Context.javaToJS(AjaxRequestManager.sharedManager(), mScope);
|
47
|
+
ScriptableObject.putProperty(mScope, "ajaxRequestManagerRegistry", wrappedAjaxRequestManagerRegistry);
|
48
|
+
|
49
|
+
evaller.start();
|
50
|
+
try {
|
51
|
+
countDownLatch.await();
|
52
|
+
} catch (InterruptedException e) {
|
53
|
+
Log.d(TAG, "Interrupted Exception when waiting for JSEvalThread");
|
54
|
+
e.printStackTrace();
|
55
|
+
}
|
56
|
+
} finally {
|
57
|
+
Context.exit();
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
private Context enterContext() {
|
62
|
+
Context ctxt = Context.enter();
|
63
|
+
// No pre-compilation
|
64
|
+
ctxt.setOptimizationLevel(-1);
|
65
|
+
return ctxt;
|
66
|
+
}
|
67
|
+
|
68
|
+
@Override
|
69
|
+
public void onDestroy() {
|
70
|
+
Log.d(TAG, "RhinoService destroyed.");
|
71
|
+
super.onDestroy();
|
72
|
+
}
|
73
|
+
|
74
|
+
public void load(Reader source, String name) {
|
75
|
+
evaller.load(source, name);
|
76
|
+
}
|
77
|
+
|
78
|
+
public void triggerEvent(String page, String eventId, String[] extraArgs) {
|
79
|
+
evaller.triggerEvent(page, eventId, extraArgs);
|
80
|
+
}
|
81
|
+
|
82
|
+
public void invokeSuccessCallback(String requestId, String response) {
|
83
|
+
evaller.ajaxSuccessfulResponse(requestId, response);
|
84
|
+
}
|
85
|
+
|
86
|
+
public void invokeFailureCallback(String requestId, int statusCode, String responseBody) {
|
87
|
+
evaller.ajaxFailureResponse(requestId, statusCode, responseBody);
|
88
|
+
}
|
89
|
+
|
90
|
+
public void callJsFunction(String function) {
|
91
|
+
evaller.callJsFunction(function);
|
92
|
+
}
|
93
|
+
|
94
|
+
public void callJsFunction(String function, String[] args) {
|
95
|
+
evaller.callJsFunction(function, args);
|
96
|
+
}
|
97
|
+
|
98
|
+
public class LocalBinder extends Binder {
|
99
|
+
public RhinoService getService() {
|
100
|
+
return RhinoService.this;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
class JSEvalThread extends Thread {
|
105
|
+
private Handler handler;
|
106
|
+
private Context ctxt;
|
107
|
+
|
108
|
+
public JSEvalThread() {
|
109
|
+
super(null, null, "js eval thread", 32768);
|
110
|
+
}
|
111
|
+
|
112
|
+
public void load(final Reader source, final String name) {
|
113
|
+
handler.post(new Runnable() {
|
114
|
+
@Override
|
115
|
+
public void run() {
|
116
|
+
try {
|
117
|
+
Log.d(TAG, "Loading file: '" + name + "'");
|
118
|
+
ctxt.evaluateReader(mScope, source, name, 0, null);
|
119
|
+
} catch (IOException e) {
|
120
|
+
Log.e(TAG, "Error loading file: '" + name + "'", e);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
});
|
124
|
+
}
|
125
|
+
|
126
|
+
public void callJsFunction(String function) {
|
127
|
+
String js = "{0}();"
|
128
|
+
.replace("{0}", function);
|
129
|
+
dispatchJs(js);
|
130
|
+
}
|
131
|
+
|
132
|
+
public void callJsFunction(String function, String[] args) {
|
133
|
+
StringBuilder sb = new StringBuilder("");
|
134
|
+
boolean first = true;
|
135
|
+
for (String arg : args) {
|
136
|
+
if (!first) {
|
137
|
+
sb.append(",");
|
138
|
+
}
|
139
|
+
first = false;
|
140
|
+
sb.append("'" + arg + "'");
|
141
|
+
}
|
142
|
+
|
143
|
+
String js = "{0}({1});"
|
144
|
+
.replace("{0}", function)
|
145
|
+
.replace("{1}", sb.toString());
|
146
|
+
|
147
|
+
Log.d(TAG, "Dispatching: " + js);
|
148
|
+
|
149
|
+
dispatchJs(js);
|
150
|
+
}
|
151
|
+
|
152
|
+
public void triggerEvent(String page, String eventId, String[] extraArgs) {
|
153
|
+
StringBuilder sb = new StringBuilder("");
|
154
|
+
for (String arg : extraArgs) {
|
155
|
+
sb.append(", '");
|
156
|
+
sb.append(arg);
|
157
|
+
sb.append("'");
|
158
|
+
}
|
159
|
+
String js = "tw.bridge.dispatchEvent('{0}', '{1}'{2});"
|
160
|
+
.replace("{0}", page)
|
161
|
+
.replace("{1}", eventId)
|
162
|
+
.replace("{2}", sb.toString());
|
163
|
+
|
164
|
+
Log.d(TAG, "Dispatching: " + js);
|
165
|
+
|
166
|
+
dispatchJs(js);
|
167
|
+
}
|
168
|
+
|
169
|
+
public void ajaxSuccessfulResponse(String requestId, String json) {
|
170
|
+
String js = "tw.bridge.requests.successfulResponse('{0}', '{1}');"
|
171
|
+
.replace("{0}", requestId)
|
172
|
+
.replace("{1}", json);
|
173
|
+
dispatchJs(js);
|
174
|
+
}
|
175
|
+
|
176
|
+
public void ajaxFailureResponse(String requestId, int statusCode, String responseBody) {
|
177
|
+
String js = "tw.bridge.requests.failureResponse('{0}', {1}, '{2}');"
|
178
|
+
.replace("{0}", requestId)
|
179
|
+
.replace("{1}", Integer.toString(statusCode))
|
180
|
+
.replace("{2}", responseBody);
|
181
|
+
dispatchJs(js);
|
182
|
+
}
|
183
|
+
|
184
|
+
public void run() {
|
185
|
+
Looper.prepare();
|
186
|
+
ctxt = enterContext();
|
187
|
+
|
188
|
+
try {
|
189
|
+
handler = new Handler();
|
190
|
+
countDownLatch.countDown();
|
191
|
+
Looper.loop();
|
192
|
+
}
|
193
|
+
finally {
|
194
|
+
Context.exit();
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
private void dispatchJs(final String js) {
|
199
|
+
handler.post(new Runnable() {
|
200
|
+
@Override
|
201
|
+
public void run() {
|
202
|
+
eval(js);
|
203
|
+
}
|
204
|
+
});
|
205
|
+
}
|
206
|
+
|
207
|
+
private void eval(String jsCode) {
|
208
|
+
ctxt.evaluateString(mScope, jsCode, "<Bridge>", 1, null);
|
209
|
+
}
|
210
|
+
|
211
|
+
}
|
212
|
+
}
|