ruboto 0.11.0 → 0.12.0.rc.0
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/Gemfile.lock +1 -1
- data/README.md +7 -5
- data/Rakefile +3 -4
- data/assets/rakelib/ruboto.rake +138 -87
- data/assets/samples/sample_broadcast_receiver.rb +1 -1
- data/assets/src/InheritingActivity.java +0 -6
- data/assets/src/RubotoActivity.java +4 -1
- data/assets/src/RubotoBroadcastReceiver.java +2 -11
- data/assets/src/RubotoService.java +6 -52
- data/assets/src/org/ruboto/EntryPointActivity.java +276 -36
- data/assets/src/org/ruboto/JRubyAdapter.java +5 -152
- data/assets/src/org/ruboto/Script.java +1 -1
- data/assets/src/org/ruboto/ScriptLoader.java +26 -44
- data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +4 -21
- data/bin/ruboto +0 -6
- data/lib/ruboto/commands/base.rb +58 -48
- data/lib/ruboto/sdk_locations.rb +23 -0
- data/lib/ruboto/sdk_versions.rb +1 -19
- data/lib/ruboto/util/build.rb +32 -32
- data/lib/ruboto/util/setup.rb +240 -0
- data/lib/ruboto/util/update.rb +12 -25
- data/lib/ruboto/util/verify.rb +7 -4
- data/lib/ruboto/util/xml_element.rb +62 -76
- data/lib/ruboto/version.rb +1 -1
- data/test/activity/image_button_activity_test.rb +2 -2
- data/test/activity/image_button_and_button_activity_test.rb +2 -2
- data/test/activity/json_activity.rb +1 -1
- data/test/activity/navigation_activity.rb +12 -12
- data/test/activity/navigation_activity_test.rb +7 -7
- data/test/activity/option_menu_activity.rb +0 -1
- data/test/activity/option_menu_activity_test.rb +2 -2
- data/test/activity/stack_activity_test.rb +10 -20
- data/test/app_test_methods.rb +0 -4
- data/test/broadcast_receiver_test.rb +16 -6
- data/test/minimal_app_test.rb +4 -12
- data/test/rake_test.rb +37 -23
- data/test/ruboto_gen_test.rb +12 -15
- data/test/sqldroid_test.rb +3 -6
- data/test/test_helper.rb +2 -0
- data/test/update_test_methods.rb +9 -9
- metadata +7 -11
@@ -1,10 +1,4 @@
|
|
1
1
|
package THE_PACKAGE;
|
2
2
|
|
3
|
-
import android.os.Bundle;
|
4
|
-
|
5
3
|
public class InheritingActivity extends org.ruboto.EntryPointActivity {
|
6
|
-
public void onCreate(Bundle bundle) {
|
7
|
-
getScriptInfo().setRubyClassName(getClass().getSimpleName());
|
8
|
-
super.onCreate(bundle);
|
9
|
-
}
|
10
4
|
}
|
@@ -48,15 +48,18 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
|
48
48
|
}
|
49
49
|
|
50
50
|
if (JRubyAdapter.isInitialized() && scriptInfo.isReadyToLoad()) {
|
51
|
-
ScriptLoader.loadScript(this
|
51
|
+
ScriptLoader.loadScript(this);
|
52
|
+
ScriptLoader.callOnCreate(this, (Object[]) args);
|
52
53
|
} else {
|
53
54
|
super.onCreate(bundle);
|
54
55
|
}
|
55
56
|
}
|
56
57
|
|
58
|
+
// FIXME(uwe): What is this for?
|
57
59
|
public boolean rubotoAttachable() {
|
58
60
|
return true;
|
59
61
|
}
|
62
|
+
// EMXIF
|
60
63
|
|
61
64
|
/****************************************************************************************
|
62
65
|
*
|
@@ -30,7 +30,7 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
|
30
30
|
|
31
31
|
public void onReceive(android.content.Context context, android.content.Intent intent) {
|
32
32
|
try {
|
33
|
-
Log.d("onReceive: " + this);
|
33
|
+
Log.d("onReceive: " + this + " " + ScriptLoader.isCalledFromJRuby() + " " + scriptLoaded);
|
34
34
|
if (ScriptLoader.isCalledFromJRuby()) {
|
35
35
|
return;
|
36
36
|
}
|
@@ -43,23 +43,14 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
|
43
43
|
}
|
44
44
|
}
|
45
45
|
|
46
|
-
// FIXME(uwe): Simplify when we stop supporting JRuby 1.6.x
|
47
|
-
if (JRubyAdapter.isJRubyPreOneSeven()) {
|
48
|
-
JRubyAdapter.put("$broadcast_receiver", this);
|
49
|
-
JRubyAdapter.put("$context", context);
|
50
|
-
JRubyAdapter.put("$intent", intent);
|
51
|
-
JRubyAdapter.runScriptlet("$broadcast_receiver.on_receive($context, $intent)");
|
52
|
-
} else if (JRubyAdapter.isJRubyOneSeven()) {
|
53
46
|
// FIXME(uwe): Simplify when we stop support for snake case aliasing interface callback methods.
|
54
47
|
if ((Boolean)JRubyAdapter.runScriptlet(scriptInfo.getRubyClassName() + ".instance_methods(false).any?{|m| m.to_sym == :onReceive}")) {
|
48
|
+
Log.d("onReceive: call method");
|
55
49
|
JRubyAdapter.runRubyMethod(this, "onReceive", new Object[]{context, intent});
|
56
50
|
} else if ((Boolean)JRubyAdapter.runScriptlet(scriptInfo.getRubyClassName() + ".instance_methods(false).any?{|m| m.to_sym == :on_receive}")) {
|
57
51
|
JRubyAdapter.runRubyMethod(this, "on_receive", new Object[]{context, intent});
|
58
52
|
}
|
59
53
|
// EMXIF
|
60
|
-
} else {
|
61
|
-
throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
|
62
|
-
}
|
63
54
|
} catch(Exception e) {
|
64
55
|
e.printStackTrace();
|
65
56
|
}
|
@@ -31,6 +31,7 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
|
31
31
|
}
|
32
32
|
}
|
33
33
|
|
34
|
+
// FIXME(uwe): Revert to generate these methods.
|
34
35
|
@Override
|
35
36
|
public int onStartCommand(android.content.Intent intent, int flags, int startId) {
|
36
37
|
if (ScriptLoader.isCalledFromJRuby()) return super.onStartCommand(intent, flags, startId);
|
@@ -48,42 +49,17 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
|
48
49
|
String rubyClassName = scriptInfo.getRubyClassName();
|
49
50
|
if (rubyClassName == null) return super.onStartCommand(intent, flags, startId);
|
50
51
|
if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :on_start_command}")) {
|
51
|
-
|
52
|
-
if (JRubyAdapter.isJRubyPreOneSeven()) {
|
53
|
-
JRubyAdapter.put("$arg_intent", intent);
|
54
|
-
JRubyAdapter.put("$arg_flags", flags);
|
55
|
-
JRubyAdapter.put("$arg_startId", startId);
|
56
|
-
JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
|
57
|
-
return (Integer) ((Number)JRubyAdapter.runScriptlet("$ruby_instance.on_start_command($arg_intent, $arg_flags, $arg_startId)")).intValue();
|
52
|
+
return (Integer) JRubyAdapter.runRubyMethod(Integer.class, scriptInfo.getRubyInstance(), "on_start_command", new Object[]{intent, flags, startId});
|
58
53
|
} else {
|
59
|
-
if (JRubyAdapter.isJRubyOneSeven()) {
|
60
|
-
return (Integer) JRubyAdapter.runRubyMethod(Integer.class, scriptInfo.getRubyInstance(), "on_start_command", new Object[]{intent, flags, startId});
|
61
|
-
} else {
|
62
|
-
throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
|
63
|
-
}
|
64
|
-
}
|
65
|
-
} else {
|
66
54
|
if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :onStartCommand}")) {
|
67
|
-
|
68
|
-
if (JRubyAdapter.isJRubyPreOneSeven()) {
|
69
|
-
JRubyAdapter.put("$arg_intent", intent);
|
70
|
-
JRubyAdapter.put("$arg_flags", flags);
|
71
|
-
JRubyAdapter.put("$arg_startId", startId);
|
72
|
-
JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
|
73
|
-
return (Integer) ((Number)JRubyAdapter.runScriptlet("$ruby_instance.onStartCommand($arg_intent, $arg_flags, $arg_startId)")).intValue();
|
74
|
-
} else {
|
75
|
-
if (JRubyAdapter.isJRubyOneSeven()) {
|
76
|
-
return (Integer) JRubyAdapter.runRubyMethod(Integer.class, scriptInfo.getRubyInstance(), "onStartCommand", new Object[]{intent, flags, startId});
|
77
|
-
} else {
|
78
|
-
throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
|
79
|
-
}
|
80
|
-
}
|
55
|
+
return (Integer) JRubyAdapter.runRubyMethod(Integer.class, scriptInfo.getRubyInstance(), "onStartCommand", new Object[]{intent, flags, startId});
|
81
56
|
} else {
|
82
57
|
return super.onStartCommand(intent, flags, startId);
|
83
58
|
}
|
84
59
|
}
|
85
60
|
}
|
86
61
|
|
62
|
+
// FIXME(uwe): Revert to generate these methods.
|
87
63
|
@Override
|
88
64
|
public android.os.IBinder onBind(android.content.Intent intent) {
|
89
65
|
if (ScriptLoader.isCalledFromJRuby()) return null;
|
@@ -100,32 +76,10 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
|
100
76
|
String rubyClassName = scriptInfo.getRubyClassName();
|
101
77
|
if (rubyClassName == null) return null;
|
102
78
|
if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :on_bind}")) {
|
103
|
-
|
104
|
-
if (JRubyAdapter.isJRubyPreOneSeven()) {
|
105
|
-
JRubyAdapter.put("$arg_intent", intent);
|
106
|
-
JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
|
107
|
-
return (android.os.IBinder) JRubyAdapter.runScriptlet("$ruby_instance.on_bind($arg_intent)");
|
108
|
-
} else {
|
109
|
-
if (JRubyAdapter.isJRubyOneSeven()) {
|
110
|
-
return (android.os.IBinder) JRubyAdapter.runRubyMethod(android.os.IBinder.class, scriptInfo.getRubyInstance(), "on_bind", intent);
|
111
|
-
} else {
|
112
|
-
throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
|
113
|
-
}
|
114
|
-
}
|
79
|
+
return (android.os.IBinder) JRubyAdapter.runRubyMethod(android.os.IBinder.class, scriptInfo.getRubyInstance(), "on_bind", intent);
|
115
80
|
} else {
|
116
81
|
if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :onBind}")) {
|
117
|
-
|
118
|
-
if (JRubyAdapter.isJRubyPreOneSeven()) {
|
119
|
-
JRubyAdapter.put("$arg_intent", intent);
|
120
|
-
JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
|
121
|
-
return (android.os.IBinder) JRubyAdapter.runScriptlet("$ruby_instance.onBind($arg_intent)");
|
122
|
-
} else {
|
123
|
-
if (JRubyAdapter.isJRubyOneSeven()) {
|
124
|
-
return (android.os.IBinder) JRubyAdapter.runRubyMethod(android.os.IBinder.class, scriptInfo.getRubyInstance(), "onBind", intent);
|
125
|
-
} else {
|
126
|
-
throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
|
127
|
-
}
|
128
|
-
}
|
82
|
+
return (android.os.IBinder) JRubyAdapter.runRubyMethod(android.os.IBinder.class, scriptInfo.getRubyInstance(), "onBind", intent);
|
129
83
|
} else {
|
130
84
|
return null;
|
131
85
|
}
|
@@ -1,5 +1,8 @@
|
|
1
1
|
package org.ruboto;
|
2
2
|
|
3
|
+
import android.app.DownloadManager;
|
4
|
+
import android.app.DownloadManager.Query;
|
5
|
+
import android.app.DownloadManager.Request;
|
3
6
|
import android.app.ProgressDialog;
|
4
7
|
import android.content.BroadcastReceiver;
|
5
8
|
import android.content.Context;
|
@@ -7,25 +10,40 @@ import android.content.DialogInterface;
|
|
7
10
|
import android.content.DialogInterface.OnCancelListener;
|
8
11
|
import android.content.Intent;
|
9
12
|
import android.content.IntentFilter;
|
13
|
+
import android.content.pm.PackageManager;
|
14
|
+
import android.database.Cursor;
|
10
15
|
import android.net.Uri;
|
11
16
|
import android.os.Bundle;
|
17
|
+
import android.provider.Settings;
|
12
18
|
import android.view.View;
|
13
19
|
import android.widget.TextView;
|
14
20
|
import android.widget.Toast;
|
15
21
|
|
22
|
+
/**
|
23
|
+
* This Activity acts as an entry point to the app. It must initialize the
|
24
|
+
* JRuby runtime before continuing its life cycle.
|
25
|
+
* While JRuby is initializing, a progress dialog is shown.
|
26
|
+
* If R.layout.splash is defined, by adding a res/layout/splash.xml file,
|
27
|
+
* this layout is displayed instead of the progress dialog.
|
28
|
+
*/
|
16
29
|
public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
17
30
|
private int splash = 0;
|
18
31
|
private ProgressDialog loadingDialog;
|
19
32
|
private boolean dialogCancelled = false;
|
20
33
|
private BroadcastReceiver receiver;
|
34
|
+
private long enqueue;
|
35
|
+
java.io.File localFile;
|
36
|
+
private static final int INSTALL_REQUEST_CODE = 4242;
|
21
37
|
|
22
38
|
// FIXME(uwe): Remove this field? Duplicated by ScriptInfo.isLoaded() ?
|
23
39
|
protected boolean appStarted = false;
|
24
40
|
// EMXIF
|
25
41
|
|
26
42
|
public void onCreate(Bundle bundle) {
|
27
|
-
Log.d("onCreate:
|
43
|
+
Log.d("EntryPointActivity onCreate:");
|
44
|
+
getScriptInfo().setRubyClassName(getClass().getSimpleName());
|
28
45
|
|
46
|
+
localFile = new java.io.File(getFilesDir(), RUBOTO_APK);
|
29
47
|
try {
|
30
48
|
splash = Class.forName(getPackageName() + ".R$layout").getField("splash").getInt(null);
|
31
49
|
} catch (Exception e) {
|
@@ -34,6 +52,8 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
34
52
|
|
35
53
|
if (JRubyAdapter.isInitialized()) {
|
36
54
|
appStarted = true;
|
55
|
+
} else {
|
56
|
+
initJRuby(true);
|
37
57
|
}
|
38
58
|
super.onCreate(bundle);
|
39
59
|
}
|
@@ -53,27 +73,8 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
53
73
|
fireRubotoActivity();
|
54
74
|
} else {
|
55
75
|
Log.d("Not initialized");
|
56
|
-
showProgress();
|
57
|
-
receiver = new BroadcastReceiver(){
|
58
|
-
public void onReceive(Context context, Intent intent) {
|
59
|
-
Log.i("received broadcast: " + intent);
|
60
|
-
Log.i("URI: " + intent.getData());
|
61
|
-
if (intent.getData().toString().equals("package:org.ruboto.core")) {
|
62
|
-
Toast.makeText(context,"Ruboto Core is now installed.",Toast.LENGTH_SHORT).show();
|
63
|
-
if (receiver != null) {
|
64
|
-
unregisterReceiver(receiver);
|
65
|
-
receiver = null;
|
66
|
-
}
|
67
|
-
showProgress();
|
68
|
-
initJRuby(false);
|
69
|
-
}
|
70
|
-
}
|
71
|
-
};
|
72
|
-
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
73
|
-
filter.addDataScheme("package");
|
74
|
-
registerReceiver(receiver, filter);
|
75
|
-
initJRuby(true);
|
76
76
|
super.onResume();
|
77
|
+
initJRuby(true);
|
77
78
|
}
|
78
79
|
}
|
79
80
|
|
@@ -98,33 +99,39 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
98
99
|
}
|
99
100
|
|
100
101
|
private void initJRuby(final boolean firstTime) {
|
102
|
+
showProgress();
|
101
103
|
new Thread(new Runnable() {
|
102
104
|
public void run() {
|
103
105
|
final boolean jrubyOk = JRubyAdapter.setUpJRuby(EntryPointActivity.this);
|
104
106
|
if (jrubyOk) {
|
105
107
|
Log.d("onResume: JRuby OK");
|
106
|
-
|
107
|
-
public void run() {
|
108
|
-
fireRubotoActivity();
|
109
|
-
}
|
110
|
-
});
|
108
|
+
fireRubotoActivity();
|
111
109
|
} else {
|
110
|
+
registerPackageInstallReceiver();
|
112
111
|
runOnUiThread(new Runnable() {
|
113
112
|
public void run() {
|
113
|
+
if (localFile.exists()) {
|
114
|
+
installDownload();
|
115
|
+
} else {
|
114
116
|
if (firstTime) {
|
115
117
|
Log.d("onResume: Checking JRuby - IN UI thread");
|
116
118
|
try {
|
117
119
|
setContentView(Class.forName(getPackageName() + ".R$layout").getField("get_ruboto_core").getInt(null));
|
120
|
+
if (hasInternetPermission()) {
|
121
|
+
getRubotoCore(null);
|
122
|
+
return;
|
123
|
+
}
|
118
124
|
} catch (Exception e) {
|
119
125
|
}
|
120
126
|
} else {
|
121
|
-
Toast.makeText(EntryPointActivity.this,"Failed to initialize Ruboto Core.",Toast.
|
127
|
+
Toast.makeText(EntryPointActivity.this,"Failed to initialize Ruboto Core.",Toast.LENGTH_LONG).show();
|
122
128
|
try {
|
123
129
|
TextView textView = (TextView) findViewById(Class.forName(getPackageName() + ".R$id").getField("text").getInt(null));
|
124
130
|
textView.setText("Woops! Ruboto Core was installed, but it failed to initialize properly! I am not sure how to proceed from here. If you can, please file an error report at http://ruboto.org/");
|
125
131
|
} catch (Exception e) {
|
126
132
|
}
|
127
133
|
}
|
134
|
+
}
|
128
135
|
hideProgress();
|
129
136
|
}
|
130
137
|
});
|
@@ -134,17 +141,42 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
134
141
|
}
|
135
142
|
|
136
143
|
private static final String RUBOTO_APK = "RubotoCore-release.apk";
|
137
|
-
private static final String RUBOTO_URL = "
|
144
|
+
private static final String RUBOTO_URL = "http://ruboto.org/downloads/" + RUBOTO_APK;
|
138
145
|
|
139
146
|
// Called when the button is pressed.
|
140
147
|
public void getRubotoCore(View view) {
|
148
|
+
try {
|
149
|
+
if (hasInternetPermission() && canInstallFromUnknownSources()) {
|
150
|
+
if (enqueue <= 0) {
|
151
|
+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
152
|
+
Request request = new Request(Uri.parse(RUBOTO_URL));
|
153
|
+
enqueue = dm.enqueue(request);
|
154
|
+
hideProgress();
|
155
|
+
showDownloadProgress("Downloading RubotoCore...");
|
156
|
+
new Thread(new Runnable() {
|
157
|
+
public void run() {
|
158
|
+
while (loadingDialog != null && enqueue > 0) {
|
159
|
+
// FIXME(uwe): Also set total bytes and bytes downloaded.
|
160
|
+
loadingDialog.setProgress(getProgressPercentage());
|
161
|
+
try {
|
162
|
+
Thread.sleep(1000);
|
163
|
+
} catch (InterruptedException ie) {
|
164
|
+
Log.e("Interupted!");
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}).start();
|
169
|
+
}
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
} catch (Exception e) {
|
173
|
+
Log.e("Exception in direct RubotoCore download: " + e);
|
174
|
+
}
|
141
175
|
try {
|
142
176
|
startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id=org.ruboto.core")));
|
143
177
|
} catch (android.content.ActivityNotFoundException anfe) {
|
144
|
-
|
145
|
-
|
146
|
-
startActivity(intent);
|
147
|
-
} catch (Exception e) {}
|
178
|
+
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(RUBOTO_URL));
|
179
|
+
startActivity(intent);
|
148
180
|
}
|
149
181
|
}
|
150
182
|
|
@@ -152,10 +184,15 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
152
184
|
if(appStarted) return;
|
153
185
|
appStarted = true;
|
154
186
|
Log.i("Starting activity");
|
155
|
-
ScriptLoader.loadScript(this
|
156
|
-
|
157
|
-
|
158
|
-
|
187
|
+
ScriptLoader.loadScript(this);
|
188
|
+
runOnUiThread(new Runnable() {
|
189
|
+
public void run() {
|
190
|
+
ScriptLoader.callOnCreate(EntryPointActivity.this, args[0]);
|
191
|
+
onStart();
|
192
|
+
onResume();
|
193
|
+
hideProgress();
|
194
|
+
}
|
195
|
+
});
|
159
196
|
}
|
160
197
|
|
161
198
|
private void showProgress() {
|
@@ -178,6 +215,35 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
178
215
|
}
|
179
216
|
}
|
180
217
|
|
218
|
+
private void showDownloadProgress(String message) {
|
219
|
+
if (loadingDialog == null) {
|
220
|
+
if (splash > 0) {
|
221
|
+
Log.i("Showing splash");
|
222
|
+
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
|
223
|
+
setContentView(splash);
|
224
|
+
} else {
|
225
|
+
Log.i("Showing progress");
|
226
|
+
loadingDialog = new ProgressDialog(this);
|
227
|
+
loadingDialog.setTitle(null);
|
228
|
+
loadingDialog.setMessage(message);
|
229
|
+
loadingDialog.setIndeterminate(false);
|
230
|
+
loadingDialog.setMax(100);
|
231
|
+
loadingDialog.setProgressStyle(android.app.ProgressDialog.STYLE_HORIZONTAL);
|
232
|
+
loadingDialog.setCancelable(true);
|
233
|
+
loadingDialog.setCanceledOnTouchOutside(false);
|
234
|
+
loadingDialog.setOnCancelListener(new OnCancelListener() {
|
235
|
+
public void onCancel(DialogInterface dialog) {
|
236
|
+
dialogCancelled = true;
|
237
|
+
finish();
|
238
|
+
}
|
239
|
+
});
|
240
|
+
loadingDialog.show();
|
241
|
+
}
|
242
|
+
} else {
|
243
|
+
loadingDialog.setMessage(message);
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
181
247
|
private void hideProgress() {
|
182
248
|
if (loadingDialog != null) {
|
183
249
|
Log.d("Hide progress");
|
@@ -186,4 +252,178 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
|
|
186
252
|
}
|
187
253
|
}
|
188
254
|
|
255
|
+
private void registerPackageInstallReceiver() {
|
256
|
+
receiver = new BroadcastReceiver(){
|
257
|
+
public void onReceive(Context context, Intent intent) {
|
258
|
+
Log.d("Received intent: " + intent + " (" + intent.getExtras() + ")");
|
259
|
+
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
|
260
|
+
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
|
261
|
+
if (downloadId == enqueue) {
|
262
|
+
if (localFile.exists()) {
|
263
|
+
return;
|
264
|
+
}
|
265
|
+
Query query = new Query();
|
266
|
+
query.setFilterById(enqueue);
|
267
|
+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
268
|
+
Cursor c = dm.query(query);
|
269
|
+
if (c.moveToFirst()) {
|
270
|
+
hideProgress();
|
271
|
+
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
|
272
|
+
if (DownloadManager.STATUS_SUCCESSFUL == status) {
|
273
|
+
storeDownload(dm, downloadId);
|
274
|
+
installDownload();
|
275
|
+
} else {
|
276
|
+
int reason = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON));
|
277
|
+
Toast.makeText(context,"Download failed (" + status + "): " + reason, Toast.LENGTH_LONG).show();
|
278
|
+
}
|
279
|
+
} else {
|
280
|
+
Toast.makeText(context,"Download diappeared!", Toast.LENGTH_LONG).show();
|
281
|
+
}
|
282
|
+
c.close();
|
283
|
+
}
|
284
|
+
} else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
|
285
|
+
if (intent.getData().toString().equals("package:org.ruboto.core")) {
|
286
|
+
Toast.makeText(context,"Ruboto Core is now installed.",Toast.LENGTH_LONG).show();
|
287
|
+
deleteFile(RUBOTO_APK);
|
288
|
+
if (receiver != null) {
|
289
|
+
unregisterReceiver(receiver);
|
290
|
+
receiver = null;
|
291
|
+
}
|
292
|
+
initJRuby(false);
|
293
|
+
} else {
|
294
|
+
Toast.makeText(context,"Installed: " + intent.getData().toString(),Toast.LENGTH_LONG).show();
|
295
|
+
}
|
296
|
+
}
|
297
|
+
}
|
298
|
+
};
|
299
|
+
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
300
|
+
filter.addDataScheme("package");
|
301
|
+
registerReceiver(receiver, filter);
|
302
|
+
IntentFilter download_filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
|
303
|
+
registerReceiver(receiver, download_filter);
|
304
|
+
}
|
305
|
+
|
306
|
+
private void storeDownload(DownloadManager dm, long downloadId) {
|
307
|
+
try {
|
308
|
+
android.os.ParcelFileDescriptor file = dm.openDownloadedFile(downloadId);
|
309
|
+
java.io.InputStream fileStream = new java.io.FileInputStream(file.getFileDescriptor());
|
310
|
+
java.io.FileOutputStream fos = openFileOutput(RUBOTO_APK, MODE_WORLD_READABLE);
|
311
|
+
byte[] buffer = new byte[1024];
|
312
|
+
int length;
|
313
|
+
while((length = fileStream.read(buffer)) > 0) {
|
314
|
+
fos.write(buffer, 0, length);
|
315
|
+
}
|
316
|
+
fos.flush();
|
317
|
+
fileStream.close();
|
318
|
+
fos.close();
|
319
|
+
dm.remove(downloadId);
|
320
|
+
enqueue = 0;
|
321
|
+
} catch (java.io.IOException ioe) {
|
322
|
+
Log.e("Exception copying RubotoCore: " + ioe);
|
323
|
+
Toast.makeText(this, "Exception copying RubotoCore: " + ioe, Toast.LENGTH_LONG).show();
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
// FIXME(uwe): Remove when we stop supporting Android < 4.0.3
|
328
|
+
private void installDownload() {
|
329
|
+
if (android.os.Build.VERSION.SDK_INT < 15) {
|
330
|
+
installDownload_10();
|
331
|
+
} else {
|
332
|
+
installDownload_15();
|
333
|
+
}
|
334
|
+
}
|
335
|
+
// EMXIF
|
336
|
+
|
337
|
+
// FIXME(uwe): Remove when we stop supporting Android < 4.0.3
|
338
|
+
private void installDownload_10() {
|
339
|
+
Uri uri = Uri.fromFile(localFile);
|
340
|
+
EntryPointActivity.this.grantUriPermission("com.android.packageinstaller", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
341
|
+
Intent installIntent = new Intent(Intent.ACTION_VIEW);
|
342
|
+
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
343
|
+
installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
344
|
+
startActivityForResult(installIntent, INSTALL_REQUEST_CODE);
|
345
|
+
}
|
346
|
+
// EMXIF
|
347
|
+
|
348
|
+
// FIXME(uwe): Use constants when we stop suporting Android < 4.0.3
|
349
|
+
private void installDownload_15() {
|
350
|
+
Uri uri = Uri.fromFile(localFile);
|
351
|
+
EntryPointActivity.this.grantUriPermission("com.android.packageinstaller", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
352
|
+
Intent installIntent = new Intent("android.intent.action.INSTALL_PACKAGE"); // Intent.ACTION_INSTALL_PACKAGE
|
353
|
+
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
354
|
+
installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
355
|
+
// FIXME(uwe): Remove when we stop supporting Android api level < 16
|
356
|
+
installIntent.putExtra("android.intent.extra.ALLOW_REPLACE", true); // Intent.EXTRA_ALLOW_REPLACE
|
357
|
+
// EMXIF
|
358
|
+
installIntent.putExtra("android.intent.extra.INSTALLER_PACKAGE_NAME", getPackageName()); // Intent.EXTRA_INSTALLER_PACKAGE_NAME
|
359
|
+
installIntent.putExtra("android.intent.extra.NOT_UNKNOWN_SOURCE", true); // Intent.EXTRA_NOT_UNKNOWN_SOURCE
|
360
|
+
installIntent.putExtra("android.intent.extra.RETURN_RESULT", true); // Intent.EXTRA_RETURN_RESULT
|
361
|
+
startActivityForResult(installIntent, INSTALL_REQUEST_CODE);
|
362
|
+
}
|
363
|
+
// EMXIF
|
364
|
+
|
365
|
+
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
366
|
+
Log.d("onActivityResult: " + requestCode + ", " + resultCode + ", " + data);
|
367
|
+
Log.d("onActivityResult: " + INSTALL_REQUEST_CODE + ", " + RESULT_OK + ", " + RESULT_CANCELED);
|
368
|
+
if (requestCode == INSTALL_REQUEST_CODE) {
|
369
|
+
if (resultCode == RESULT_OK) {
|
370
|
+
Log.d("onActivityResult: Install OK.");
|
371
|
+
} else if (resultCode == RESULT_CANCELED) {
|
372
|
+
Log.d("onActivityResult: Install canceled.");
|
373
|
+
// FIXME(uwe): Maybe show a dialog explaining that RubotoCore is needed and try again?
|
374
|
+
deleteFile(RUBOTO_APK);
|
375
|
+
if (!JRubyAdapter.isInitialized()) {
|
376
|
+
finish();
|
377
|
+
}
|
378
|
+
// EMXIF
|
379
|
+
} else {
|
380
|
+
Log.e("onActivityResult: resultCode: " + resultCode);
|
381
|
+
}
|
382
|
+
}
|
383
|
+
super.onActivityResult(requestCode, resultCode, data);
|
384
|
+
}
|
385
|
+
|
386
|
+
private boolean hasInternetPermission() {
|
387
|
+
String permission = "android.permission.INTERNET";
|
388
|
+
int res = checkCallingOrSelfPermission(permission);
|
389
|
+
return (res == PackageManager.PERMISSION_GRANTED);
|
390
|
+
}
|
391
|
+
|
392
|
+
private boolean canInstallFromUnknownSources() {
|
393
|
+
Uri settingsUri = Settings.Secure.CONTENT_URI;
|
394
|
+
String[] projection = new String[]{Settings.System.VALUE};
|
395
|
+
String selection = Settings.Secure.NAME + " = ? AND " + Settings.Secure.VALUE + " = ?";
|
396
|
+
|
397
|
+
// FIXME(uwe): Use android.provider.Settings.Global.INSTALL_NON_MARKET_APPS
|
398
|
+
// when we stop supporting Android api level < 17
|
399
|
+
String[] selectionArgs = {Settings.Secure.INSTALL_NON_MARKET_APPS, String.valueOf(1)};
|
400
|
+
// EMXIF
|
401
|
+
|
402
|
+
Cursor query = getContentResolver().query(settingsUri, projection,
|
403
|
+
selection, selectionArgs, null);
|
404
|
+
return query.getCount() == 1;
|
405
|
+
}
|
406
|
+
|
407
|
+
// Get the downloaded percent
|
408
|
+
private int getProgressPercentage() {
|
409
|
+
int downloadedBytesSoFar = 0, totalBytes = 0, percentage = 0;
|
410
|
+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
411
|
+
try {
|
412
|
+
Cursor c = dm.query(new DownloadManager.Query().setFilterById(enqueue));
|
413
|
+
if (c.moveToFirst()) {
|
414
|
+
int soFarIndex =c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
|
415
|
+
downloadedBytesSoFar = (int) c.getLong(soFarIndex);
|
416
|
+
int totalSizeIndex = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
|
417
|
+
totalBytes = (int) c.getLong(totalSizeIndex);
|
418
|
+
}
|
419
|
+
System.out.println("PERCEN ------" + downloadedBytesSoFar
|
420
|
+
+ " ------ " + totalBytes + "****" + percentage);
|
421
|
+
percentage = (downloadedBytesSoFar * 100 / totalBytes);
|
422
|
+
System.out.println("percentage % " + percentage);
|
423
|
+
} catch (Exception e) {
|
424
|
+
e.printStackTrace();
|
425
|
+
}
|
426
|
+
return percentage;
|
427
|
+
}
|
428
|
+
|
189
429
|
}
|