ruboto 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,23 +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;
6
- import android.app.ProgressDialog;
7
- import android.content.BroadcastReceiver;
8
3
  import android.content.Context;
9
- import android.content.DialogInterface;
10
- import android.content.DialogInterface.OnCancelListener;
11
4
  import android.content.Intent;
12
- import android.content.IntentFilter;
13
- import android.content.pm.PackageManager;
14
- import android.database.Cursor;
15
- import android.net.Uri;
16
5
  import android.os.Bundle;
17
- import android.provider.Settings;
18
- import android.view.View;
19
- import android.widget.TextView;
20
- import android.widget.Toast;
21
6
 
22
7
  /**
23
8
  * This Activity acts as an entry point to the app. It must initialize the
@@ -27,41 +12,22 @@ import android.widget.Toast;
27
12
  * this layout is displayed instead of the progress dialog.
28
13
  */
29
14
  public class EntryPointActivity extends org.ruboto.RubotoActivity {
30
- private int splash = 0;
31
- private ProgressDialog loadingDialog;
32
- private boolean dialogCancelled = false;
33
- private BroadcastReceiver receiver;
34
- private long enqueue;
35
- java.io.File localFile;
36
- private static final int INSTALL_REQUEST_CODE = 4242;
37
15
 
38
- // FIXME(uwe): Remove this field? Duplicated by ScriptInfo.isLoaded() ?
39
- protected boolean appStarted = false;
40
- // EMXIF
41
-
42
- public void onCreate(Bundle bundle) {
16
+ public void onCreate(Bundle bundle) {
43
17
  Log.d("EntryPointActivity onCreate:");
44
- getScriptInfo().setRubyClassName(getClass().getSimpleName());
45
-
46
- localFile = new java.io.File(getFilesDir(), RUBOTO_APK);
47
- try {
48
- splash = Class.forName(getPackageName() + ".R$layout").getField("splash").getInt(null);
49
- } catch (Exception e) {
50
- splash = -1;
51
- }
18
+ getScriptInfo().setRubyClassName(getClass().getSimpleName());
52
19
 
53
- if (JRubyAdapter.isInitialized()) {
54
- appStarted = true;
55
- } else {
56
- initJRuby(true);
57
- }
58
- super.onCreate(bundle);
59
- }
20
+ if (!JRubyAdapter.isInitialized()) {
21
+ showSplash();
22
+ finish();
23
+ }
24
+ super.onCreate(bundle);
25
+ }
60
26
 
61
27
  public void onResume() {
62
28
  Log.d("onResume: ");
63
29
 
64
- if(appStarted) {
30
+ if(getScriptInfo().isLoaded()) {
65
31
  Log.d("onResume: App already started!");
66
32
  super.onResume();
67
33
  return;
@@ -73,357 +39,45 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
73
39
  fireRubotoActivity();
74
40
  } else {
75
41
  Log.d("Not initialized");
76
- super.onResume();
77
- initJRuby(true);
42
+ showSplash();
43
+ finish();
78
44
  }
45
+ super.onResume();
79
46
  }
80
47
 
81
48
  public void onPause() {
82
49
  Log.d("onPause: ");
83
-
84
- if (receiver != null) {
85
- unregisterReceiver(receiver);
86
- receiver = null;
87
- }
88
50
  super.onPause();
89
51
  }
90
52
 
91
53
  public void onDestroy() {
92
54
  Log.d("onDestroy: ");
93
-
94
55
  super.onDestroy();
95
- if (dialogCancelled) {
96
- System.runFinalizersOnExit(true);
97
- System.exit(0);
98
- }
99
- }
100
-
101
- private void initJRuby(final boolean firstTime) {
102
- showProgress();
103
- new Thread(new Runnable() {
104
- public void run() {
105
- final boolean jrubyOk = JRubyAdapter.setUpJRuby(EntryPointActivity.this);
106
- if (jrubyOk) {
107
- Log.d("onResume: JRuby OK");
108
- fireRubotoActivity();
109
- } else {
110
- registerPackageInstallReceiver();
111
- runOnUiThread(new Runnable() {
112
- public void run() {
113
- if (localFile.exists()) {
114
- installDownload();
115
- } else {
116
- if (firstTime) {
117
- Log.d("onResume: Checking JRuby - IN UI thread");
118
- try {
119
- setContentView(Class.forName(getPackageName() + ".R$layout").getField("get_ruboto_core").getInt(null));
120
- if (hasInternetPermission()) {
121
- getRubotoCore(null);
122
- return;
123
- }
124
- } catch (Exception e) {
125
- }
126
- } else {
127
- Toast.makeText(EntryPointActivity.this,"Failed to initialize Ruboto Core.",Toast.LENGTH_LONG).show();
128
- try {
129
- TextView textView = (TextView) findViewById(Class.forName(getPackageName() + ".R$id").getField("text").getInt(null));
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/");
131
- } catch (Exception e) {
132
- }
133
- }
134
- }
135
- hideProgress();
136
- }
137
- });
138
- }
139
- }
140
- }).start();
141
56
  }
142
57
 
143
- private static final String RUBOTO_APK = "RubotoCore-release.apk";
144
- private static final String RUBOTO_URL = "http://ruboto.org/downloads/" + RUBOTO_APK;
145
-
146
- // Called when the button is pressed.
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
- }
175
- try {
176
- startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id=org.ruboto.core")));
177
- } catch (android.content.ActivityNotFoundException anfe) {
178
- Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(RUBOTO_URL));
179
- startActivity(intent);
180
- }
181
- }
182
58
 
183
59
  protected void fireRubotoActivity() {
184
- if(appStarted) return;
185
- appStarted = true;
60
+ if(getScriptInfo().isLoaded()) return;
186
61
  Log.i("Starting activity");
187
62
  ScriptLoader.loadScript(this);
188
63
  runOnUiThread(new Runnable() {
189
- public void run() {
190
- ScriptLoader.callOnCreate(EntryPointActivity.this, args[0]);
191
- onStart();
192
- onResume();
193
- hideProgress();
194
- }
195
- });
196
- }
197
-
198
- private void showProgress() {
199
- if (loadingDialog == null) {
200
- if (splash > 0) {
201
- Log.i("Showing splash");
202
- requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
203
- setContentView(splash);
204
- } else {
205
- Log.i("Showing progress");
206
- loadingDialog = ProgressDialog.show(this, null, "Starting...", true, true);
207
- loadingDialog.setCanceledOnTouchOutside(false);
208
- loadingDialog.setOnCancelListener(new OnCancelListener() {
209
- public void onCancel(DialogInterface dialog) {
210
- dialogCancelled = true;
211
- finish();
212
- }
213
- });
214
- }
215
- }
216
- }
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
-
247
- private void hideProgress() {
248
- if (loadingDialog != null) {
249
- Log.d("Hide progress");
250
- loadingDialog.dismiss();
251
- loadingDialog = null;
252
- }
253
- }
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);
64
+ public void run() {
65
+ ScriptLoader.callOnCreate(EntryPointActivity.this, args[0]);
66
+ onStart();
67
+ onResume();
68
+ }
69
+ });
390
70
  }
391
71
 
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;
72
+ private void showSplash() {
73
+ Intent splashIntent = new Intent(this, SplashActivity.class);
74
+ splashIntent.putExtra(Intent.EXTRA_INTENT, futureIntent());
75
+ startActivity(splashIntent);
405
76
  }
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;
77
+
78
+ // The Intent to to call when done. Defaults to calling this Activity again.
79
+ // Override to change.
80
+ protected Intent futureIntent() {
81
+ return new Intent(this, this.getClass());
427
82
  }
428
-
429
83
  }
@@ -150,6 +150,7 @@ public class JRubyAdapter {
150
150
 
151
151
  // Used to enable JRuby to generate proxy classes
152
152
  System.setProperty("jruby.ji.proxyClassFactory", "org.ruboto.DalvikProxyClassFactory");
153
+ System.setProperty("jruby.ji.upper.case.package.name.allowed", "true");
153
154
  System.setProperty("jruby.class.cache.path", appContext.getDir("dex", 0).getAbsolutePath());
154
155
 
155
156
  ClassLoader classLoader;
@@ -49,61 +49,10 @@ public class Script {
49
49
  ).replace("__", "_").toLowerCase();
50
50
  }
51
51
 
52
- // Private static methods
53
-
54
- // private static void copyAssets(Context context, String directory) {
55
- // File dest = new File(new File(scriptsDirFile).getParentFile(), directory);
56
- // if (dest.exists() || dest.mkdir()) {
57
- // copyScripts(directory, dest, context.getAssets());
58
- // } else {
59
- // throw new RuntimeException("Unable to create scripts directory: " + dest);
60
- // }
61
- // }
62
-
63
- // private static void copyScripts(String from, File to, AssetManager assets) {
64
- // try {
65
- // byte[] buffer = new byte[8192];
66
- // for (String f : assets.list(from)) {
67
- // File dest = new File(to, f);
68
- //
69
- // if (dest.exists()) {
70
- // continue;
71
- // }
72
- //
73
- // Log.d("copying file from " + from + "/" + f + " to " + dest);
74
- //
75
- // if (assets.list(from + "/" + f).length == 0) {
76
- // InputStream is = assets.open(from + "/" + f);
77
- // OutputStream fos = new BufferedOutputStream(new FileOutputStream(dest), 8192);
78
- //
79
- // int n;
80
- // while ((n = is.read(buffer, 0, buffer.length)) != -1) {
81
- // fos.write(buffer, 0, n);
82
- // }
83
- // is.close();
84
- // fos.close();
85
- // } else {
86
- // dest.mkdir();
87
- // copyScripts(from + "/" + f, dest, assets);
88
- // }
89
- // }
90
- // } catch (IOException iox) {
91
- // Log.e("error copying scripts", iox);
92
- // }
93
- // }
94
-
95
- /*************************************************************************************************
96
- *
97
- * Constructors
98
- */
99
52
  public Script(String name) {
100
53
  this.name = name;
101
54
  }
102
55
 
103
- /*************************************************************************************************
104
- *
105
- * Instance methods
106
- */
107
56
  public String execute() throws IOException {
108
57
  return JRubyAdapter.runScriptlet(getContents()).toString();
109
58
  }