ruboto 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -3
- data/RELEASE_CANDICATE_DOC +4 -5
- data/RELEASE_DOC +49 -45
- data/Rakefile +20 -9
- data/assets/rakelib/ruboto.rake +32 -39
- data/assets/res/drawable/get_ruboto_core.png +0 -0
- data/assets/res/drawable-hdpi/ic_launcher.png +0 -0
- data/assets/res/drawable-ldpi/ic_launcher.png +0 -0
- data/assets/res/drawable-mdpi/ic_launcher.png +0 -0
- data/assets/src/RubotoActivity.java +3 -14
- data/assets/src/org/ruboto/EntryPointActivity.java +28 -374
- data/assets/src/org/ruboto/JRubyAdapter.java +1 -0
- data/assets/src/org/ruboto/Script.java +0 -51
- data/assets/src/org/ruboto/SplashActivity.java +394 -0
- data/assets/src/ruboto/activity.rb +22 -3
- data/lib/ruboto/commands/base.rb +7 -5
- data/lib/ruboto/util/emulator.rb +9 -6
- data/lib/ruboto/util/setup.rb +17 -19
- data/lib/ruboto/util/update.rb +38 -29
- data/lib/ruboto/version.rb +1 -1
- data/test/activity/navigation_activity.rb +1 -0
- data/test/activity/navigation_activity_test.rb +4 -0
- data/test/activity/ruby_file_activity.rb +2 -1
- data/test/minimal_app_test.rb +11 -31
- data/test/ruboto_gen_test.rb +9 -7
- data/test/ruboto_update_test.rb +38 -7
- data/test/splash_test.rb +50 -0
- data/test/test_helper.rb +8 -2
- data/test/uppercase_package_name_test.rb +16 -0
- metadata +5 -2
@@ -0,0 +1,394 @@
|
|
1
|
+
package org.ruboto;
|
2
|
+
|
3
|
+
import android.app.Activity;
|
4
|
+
import android.app.DownloadManager;
|
5
|
+
import android.app.DownloadManager.Query;
|
6
|
+
import android.app.DownloadManager.Request;
|
7
|
+
import android.app.ProgressDialog;
|
8
|
+
import android.content.BroadcastReceiver;
|
9
|
+
import android.content.Context;
|
10
|
+
import android.content.DialogInterface;
|
11
|
+
import android.content.DialogInterface.OnCancelListener;
|
12
|
+
import android.content.Intent;
|
13
|
+
import android.content.IntentFilter;
|
14
|
+
import android.content.pm.PackageManager;
|
15
|
+
import android.database.Cursor;
|
16
|
+
import android.net.Uri;
|
17
|
+
import android.os.Bundle;
|
18
|
+
import android.provider.Settings;
|
19
|
+
import android.view.View;
|
20
|
+
import android.widget.TextView;
|
21
|
+
import android.widget.Toast;
|
22
|
+
|
23
|
+
|
24
|
+
public class SplashActivity extends Activity {
|
25
|
+
private int splash = 0;
|
26
|
+
private ProgressDialog loadingDialog;
|
27
|
+
private boolean dialogCancelled = false;
|
28
|
+
private BroadcastReceiver receiver;
|
29
|
+
private long enqueue;
|
30
|
+
java.io.File localFile;
|
31
|
+
private static final int INSTALL_REQUEST_CODE = 4242;
|
32
|
+
|
33
|
+
public void onCreate(Bundle bundle) {
|
34
|
+
Log.d("SplashActivity onCreate:");
|
35
|
+
localFile = new java.io.File(getFilesDir(), RUBOTO_APK);
|
36
|
+
try {
|
37
|
+
splash = Class.forName(getPackageName() + ".R$layout").getField("splash").getInt(null);
|
38
|
+
} catch (Exception e) {
|
39
|
+
splash = -1;
|
40
|
+
}
|
41
|
+
if (!JRubyAdapter.isInitialized()) {
|
42
|
+
initJRuby(true);
|
43
|
+
}
|
44
|
+
super.onCreate(bundle);
|
45
|
+
}
|
46
|
+
|
47
|
+
public void onResume() {
|
48
|
+
Log.d("onResume: ");
|
49
|
+
if (!JRubyAdapter.isInitialized() && receiver == null) {
|
50
|
+
registerPackageInstallReceiver();
|
51
|
+
}
|
52
|
+
super.onResume();
|
53
|
+
}
|
54
|
+
|
55
|
+
public void onPause() {
|
56
|
+
Log.d("onPause: ");
|
57
|
+
if (receiver != null) {
|
58
|
+
unregisterReceiver(receiver);
|
59
|
+
receiver = null;
|
60
|
+
}
|
61
|
+
super.onPause();
|
62
|
+
}
|
63
|
+
|
64
|
+
public void onDestroy() {
|
65
|
+
Log.d("onDestroy: ");
|
66
|
+
super.onDestroy();
|
67
|
+
if (dialogCancelled) {
|
68
|
+
System.runFinalizersOnExit(true);
|
69
|
+
System.exit(0);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
private void initJRuby(final boolean firstTime) {
|
74
|
+
showProgress();
|
75
|
+
new Thread(new Runnable() {
|
76
|
+
public void run() {
|
77
|
+
final boolean jrubyOk = JRubyAdapter.setUpJRuby(SplashActivity.this);
|
78
|
+
if (jrubyOk) {
|
79
|
+
Log.d("onResume: JRuby OK");
|
80
|
+
startUserActivity();
|
81
|
+
hideProgress();
|
82
|
+
finish();
|
83
|
+
} else {
|
84
|
+
registerPackageInstallReceiver();
|
85
|
+
runOnUiThread(new Runnable() {
|
86
|
+
public void run() {
|
87
|
+
if (localFile.exists()) {
|
88
|
+
installDownload();
|
89
|
+
} else {
|
90
|
+
if (firstTime) {
|
91
|
+
Log.d("onResume: Checking JRuby - IN UI thread");
|
92
|
+
try {
|
93
|
+
setContentView(Class.forName(getPackageName() + ".R$layout").getField("get_ruboto_core").getInt(null));
|
94
|
+
if (hasInternetPermission()) {
|
95
|
+
getRubotoCore(null);
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
} catch (Exception e) {
|
99
|
+
}
|
100
|
+
} else {
|
101
|
+
Toast.makeText(SplashActivity.this,"Failed to initialize Ruboto Core.",Toast.LENGTH_LONG).show();
|
102
|
+
try {
|
103
|
+
TextView textView = (TextView) findViewById(Class.forName(getPackageName() + ".R$id").getField("text").getInt(null));
|
104
|
+
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/");
|
105
|
+
} catch (Exception e) {
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
hideProgress();
|
110
|
+
}
|
111
|
+
});
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}).start();
|
115
|
+
}
|
116
|
+
|
117
|
+
private static final String RUBOTO_APK = "RubotoCore-release.apk";
|
118
|
+
private static final String RUBOTO_URL = "http://ruboto.org/downloads/" + RUBOTO_APK;
|
119
|
+
|
120
|
+
// Called when the button is pressed.
|
121
|
+
public void getRubotoCore(View view) {
|
122
|
+
try {
|
123
|
+
if (hasInternetPermission() && canInstallFromUnknownSources()) {
|
124
|
+
if (enqueue <= 0) {
|
125
|
+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
126
|
+
Request request = new Request(Uri.parse(RUBOTO_URL));
|
127
|
+
enqueue = dm.enqueue(request);
|
128
|
+
hideProgress();
|
129
|
+
showDownloadProgress("Downloading RubotoCore...");
|
130
|
+
new Thread(new Runnable() {
|
131
|
+
public void run() {
|
132
|
+
while (loadingDialog != null && enqueue > 0) {
|
133
|
+
// FIXME(uwe): Also set total bytes and bytes downloaded.
|
134
|
+
loadingDialog.setProgress(getProgressPercentage());
|
135
|
+
try {
|
136
|
+
Thread.sleep(1000);
|
137
|
+
} catch (InterruptedException ie) {
|
138
|
+
Log.e("Interupted!");
|
139
|
+
}
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}).start();
|
143
|
+
}
|
144
|
+
return;
|
145
|
+
}
|
146
|
+
} catch (Exception e) {
|
147
|
+
Log.e("Exception in direct RubotoCore download: " + e);
|
148
|
+
}
|
149
|
+
try {
|
150
|
+
startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id=org.ruboto.core")));
|
151
|
+
} catch (android.content.ActivityNotFoundException anfe) {
|
152
|
+
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(RUBOTO_URL));
|
153
|
+
startActivity(intent);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
private void showProgress() {
|
158
|
+
if (loadingDialog == null) {
|
159
|
+
if (splash > 0) {
|
160
|
+
Log.i("Showing splash");
|
161
|
+
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
|
162
|
+
setContentView(splash);
|
163
|
+
} else {
|
164
|
+
Log.i("Showing progress");
|
165
|
+
loadingDialog = ProgressDialog.show(this, null, "Starting...", true, true);
|
166
|
+
loadingDialog.setCanceledOnTouchOutside(false);
|
167
|
+
loadingDialog.setOnCancelListener(new OnCancelListener() {
|
168
|
+
public void onCancel(DialogInterface dialog) {
|
169
|
+
dialogCancelled = true;
|
170
|
+
finish();
|
171
|
+
}
|
172
|
+
});
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
private void showDownloadProgress(String message) {
|
178
|
+
if (loadingDialog == null) {
|
179
|
+
if (splash > 0) {
|
180
|
+
Log.i("Showing splash");
|
181
|
+
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
|
182
|
+
setContentView(splash);
|
183
|
+
} else {
|
184
|
+
Log.i("Showing progress");
|
185
|
+
loadingDialog = new ProgressDialog(this);
|
186
|
+
loadingDialog.setTitle(null);
|
187
|
+
loadingDialog.setMessage(message);
|
188
|
+
loadingDialog.setIndeterminate(false);
|
189
|
+
loadingDialog.setMax(100);
|
190
|
+
loadingDialog.setProgressStyle(android.app.ProgressDialog.STYLE_HORIZONTAL);
|
191
|
+
loadingDialog.setCancelable(true);
|
192
|
+
loadingDialog.setCanceledOnTouchOutside(false);
|
193
|
+
loadingDialog.setOnCancelListener(new OnCancelListener() {
|
194
|
+
public void onCancel(DialogInterface dialog) {
|
195
|
+
dialogCancelled = true;
|
196
|
+
finish();
|
197
|
+
}
|
198
|
+
});
|
199
|
+
loadingDialog.show();
|
200
|
+
}
|
201
|
+
} else {
|
202
|
+
loadingDialog.setMessage(message);
|
203
|
+
}
|
204
|
+
}
|
205
|
+
|
206
|
+
private void hideProgress() {
|
207
|
+
if (loadingDialog != null) {
|
208
|
+
Log.d("Hide progress");
|
209
|
+
loadingDialog.dismiss();
|
210
|
+
loadingDialog = null;
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
private void registerPackageInstallReceiver() {
|
215
|
+
receiver = new BroadcastReceiver(){
|
216
|
+
public void onReceive(Context context, Intent intent) {
|
217
|
+
Log.d("Received intent: " + intent + " (" + intent.getExtras() + ")");
|
218
|
+
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
|
219
|
+
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
|
220
|
+
if (downloadId == enqueue) {
|
221
|
+
if (localFile.exists()) {
|
222
|
+
return;
|
223
|
+
}
|
224
|
+
Query query = new Query();
|
225
|
+
query.setFilterById(enqueue);
|
226
|
+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
227
|
+
Cursor c = dm.query(query);
|
228
|
+
if (c.moveToFirst()) {
|
229
|
+
hideProgress();
|
230
|
+
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
|
231
|
+
if (DownloadManager.STATUS_SUCCESSFUL == status) {
|
232
|
+
storeDownload(dm, downloadId);
|
233
|
+
installDownload();
|
234
|
+
} else {
|
235
|
+
int reason = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_REASON));
|
236
|
+
Toast.makeText(context,"Download failed (" + status + "): " + reason, Toast.LENGTH_LONG).show();
|
237
|
+
}
|
238
|
+
} else {
|
239
|
+
Toast.makeText(context,"Download diappeared!", Toast.LENGTH_LONG).show();
|
240
|
+
}
|
241
|
+
c.close();
|
242
|
+
}
|
243
|
+
} else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
|
244
|
+
if (intent.getData().toString().equals("package:org.ruboto.core")) {
|
245
|
+
Toast.makeText(context,"Ruboto Core is now installed.",Toast.LENGTH_LONG).show();
|
246
|
+
deleteFile(RUBOTO_APK);
|
247
|
+
if (receiver != null) {
|
248
|
+
unregisterReceiver(receiver);
|
249
|
+
receiver = null;
|
250
|
+
}
|
251
|
+
initJRuby(false);
|
252
|
+
} else {
|
253
|
+
Toast.makeText(context,"Installed: " + intent.getData().toString(),Toast.LENGTH_LONG).show();
|
254
|
+
}
|
255
|
+
}
|
256
|
+
}
|
257
|
+
};
|
258
|
+
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
259
|
+
filter.addDataScheme("package");
|
260
|
+
registerReceiver(receiver, filter);
|
261
|
+
IntentFilter download_filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
|
262
|
+
registerReceiver(receiver, download_filter);
|
263
|
+
}
|
264
|
+
|
265
|
+
private void storeDownload(DownloadManager dm, long downloadId) {
|
266
|
+
try {
|
267
|
+
android.os.ParcelFileDescriptor file = dm.openDownloadedFile(downloadId);
|
268
|
+
java.io.InputStream fileStream = new java.io.FileInputStream(file.getFileDescriptor());
|
269
|
+
java.io.FileOutputStream fos = openFileOutput(RUBOTO_APK, MODE_WORLD_READABLE);
|
270
|
+
byte[] buffer = new byte[1024];
|
271
|
+
int length;
|
272
|
+
while((length = fileStream.read(buffer)) > 0) {
|
273
|
+
fos.write(buffer, 0, length);
|
274
|
+
}
|
275
|
+
fos.flush();
|
276
|
+
fileStream.close();
|
277
|
+
fos.close();
|
278
|
+
dm.remove(downloadId);
|
279
|
+
enqueue = 0;
|
280
|
+
} catch (java.io.IOException ioe) {
|
281
|
+
Log.e("Exception copying RubotoCore: " + ioe);
|
282
|
+
Toast.makeText(this, "Exception copying RubotoCore: " + ioe, Toast.LENGTH_LONG).show();
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
// FIXME(uwe): Remove when we stop supporting Android < 4.0.3
|
287
|
+
private void installDownload() {
|
288
|
+
if (android.os.Build.VERSION.SDK_INT < 15) {
|
289
|
+
installDownload_10();
|
290
|
+
} else {
|
291
|
+
installDownload_15();
|
292
|
+
}
|
293
|
+
}
|
294
|
+
// EMXIF
|
295
|
+
|
296
|
+
// FIXME(uwe): Remove when we stop supporting Android < 4.0.3
|
297
|
+
private void installDownload_10() {
|
298
|
+
Uri uri = Uri.fromFile(localFile);
|
299
|
+
SplashActivity.this.grantUriPermission("com.android.packageinstaller", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
300
|
+
Intent installIntent = new Intent(Intent.ACTION_VIEW);
|
301
|
+
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
302
|
+
installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
303
|
+
startActivityForResult(installIntent, INSTALL_REQUEST_CODE);
|
304
|
+
}
|
305
|
+
// EMXIF
|
306
|
+
|
307
|
+
// FIXME(uwe): Use constants when we stop suporting Android < 4.0.3
|
308
|
+
private void installDownload_15() {
|
309
|
+
Uri uri = Uri.fromFile(localFile);
|
310
|
+
SplashActivity.this.grantUriPermission("com.android.packageinstaller", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
311
|
+
Intent installIntent = new Intent("android.intent.action.INSTALL_PACKAGE"); // Intent.ACTION_INSTALL_PACKAGE
|
312
|
+
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
313
|
+
installIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
314
|
+
// FIXME(uwe): Remove when we stop supporting Android api level < 16
|
315
|
+
installIntent.putExtra("android.intent.extra.ALLOW_REPLACE", true); // Intent.EXTRA_ALLOW_REPLACE
|
316
|
+
// EMXIF
|
317
|
+
installIntent.putExtra("android.intent.extra.INSTALLER_PACKAGE_NAME", getPackageName()); // Intent.EXTRA_INSTALLER_PACKAGE_NAME
|
318
|
+
installIntent.putExtra("android.intent.extra.NOT_UNKNOWN_SOURCE", true); // Intent.EXTRA_NOT_UNKNOWN_SOURCE
|
319
|
+
installIntent.putExtra("android.intent.extra.RETURN_RESULT", true); // Intent.EXTRA_RETURN_RESULT
|
320
|
+
startActivityForResult(installIntent, INSTALL_REQUEST_CODE);
|
321
|
+
}
|
322
|
+
// EMXIF
|
323
|
+
|
324
|
+
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
325
|
+
Log.d("onActivityResult: " + requestCode + ", " + resultCode + ", " + data);
|
326
|
+
Log.d("onActivityResult: " + INSTALL_REQUEST_CODE + ", " + RESULT_OK + ", " + RESULT_CANCELED);
|
327
|
+
if (requestCode == INSTALL_REQUEST_CODE) {
|
328
|
+
if (resultCode == RESULT_OK) {
|
329
|
+
Log.d("onActivityResult: Install OK.");
|
330
|
+
} else if (resultCode == RESULT_CANCELED) {
|
331
|
+
Log.d("onActivityResult: Install canceled.");
|
332
|
+
// FIXME(uwe): Maybe show a dialog explaining that RubotoCore is needed and try again?
|
333
|
+
deleteFile(RUBOTO_APK);
|
334
|
+
if (!JRubyAdapter.isInitialized()) {
|
335
|
+
finish();
|
336
|
+
}
|
337
|
+
// EMXIF
|
338
|
+
} else {
|
339
|
+
Log.e("onActivityResult: resultCode: " + resultCode);
|
340
|
+
}
|
341
|
+
}
|
342
|
+
super.onActivityResult(requestCode, resultCode, data);
|
343
|
+
}
|
344
|
+
|
345
|
+
private boolean hasInternetPermission() {
|
346
|
+
String permission = "android.permission.INTERNET";
|
347
|
+
int res = checkCallingOrSelfPermission(permission);
|
348
|
+
return (res == PackageManager.PERMISSION_GRANTED);
|
349
|
+
}
|
350
|
+
|
351
|
+
private boolean canInstallFromUnknownSources() {
|
352
|
+
Uri settingsUri = Settings.Secure.CONTENT_URI;
|
353
|
+
String[] projection = new String[]{Settings.System.VALUE};
|
354
|
+
String selection = Settings.Secure.NAME + " = ? AND " + Settings.Secure.VALUE + " = ?";
|
355
|
+
|
356
|
+
// FIXME(uwe): Use android.provider.Settings.Global.INSTALL_NON_MARKET_APPS
|
357
|
+
// when we stop supporting Android api level < 17
|
358
|
+
String[] selectionArgs = {Settings.Secure.INSTALL_NON_MARKET_APPS, String.valueOf(1)};
|
359
|
+
// EMXIF
|
360
|
+
|
361
|
+
Cursor query = getContentResolver().query(settingsUri, projection,
|
362
|
+
selection, selectionArgs, null);
|
363
|
+
return query.getCount() == 1;
|
364
|
+
}
|
365
|
+
|
366
|
+
// Get the downloaded percent
|
367
|
+
private int getProgressPercentage() {
|
368
|
+
int downloadedBytesSoFar = 0, totalBytes = 0, percentage = 0;
|
369
|
+
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
370
|
+
try {
|
371
|
+
Cursor c = dm.query(new DownloadManager.Query().setFilterById(enqueue));
|
372
|
+
if (c.moveToFirst()) {
|
373
|
+
int soFarIndex =c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
|
374
|
+
downloadedBytesSoFar = (int) c.getLong(soFarIndex);
|
375
|
+
int totalSizeIndex = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
|
376
|
+
totalBytes = (int) c.getLong(totalSizeIndex);
|
377
|
+
}
|
378
|
+
System.out.println("PERCEN ------" + downloadedBytesSoFar
|
379
|
+
+ " ------ " + totalBytes + "****" + percentage);
|
380
|
+
percentage = (downloadedBytesSoFar * 100 / totalBytes);
|
381
|
+
System.out.println("percentage % " + percentage);
|
382
|
+
} catch (Exception e) {
|
383
|
+
e.printStackTrace();
|
384
|
+
}
|
385
|
+
return percentage;
|
386
|
+
}
|
387
|
+
|
388
|
+
private void startUserActivity() {
|
389
|
+
if (getIntent().hasExtra(Intent.EXTRA_INTENT)) {
|
390
|
+
startActivity((Intent)getIntent().getParcelableExtra(Intent.EXTRA_INTENT));
|
391
|
+
}
|
392
|
+
}
|
393
|
+
|
394
|
+
}
|
@@ -14,9 +14,24 @@ require 'ruboto/package'
|
|
14
14
|
#
|
15
15
|
module Ruboto
|
16
16
|
module Context
|
17
|
-
def start_ruboto_dialog(
|
18
|
-
|
19
|
-
|
17
|
+
def start_ruboto_dialog(class_name = nil, options = nil, &block)
|
18
|
+
if options.nil?
|
19
|
+
if class_name.is_a?(Hash)
|
20
|
+
options = class_name
|
21
|
+
class_name = nil
|
22
|
+
else
|
23
|
+
options = {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
unless options.key?(:java_class)
|
28
|
+
java_import 'org.ruboto.RubotoDialog'
|
29
|
+
options[:java_class] = RubotoDialog
|
30
|
+
end
|
31
|
+
|
32
|
+
options[:theme] = android.R.style::Theme_Dialog unless options.key?(:theme)
|
33
|
+
|
34
|
+
start_ruboto_activity(class_name, options, &block)
|
20
35
|
end
|
21
36
|
|
22
37
|
def start_ruboto_activity(class_name = nil, options = nil, &block)
|
@@ -43,6 +58,7 @@ module Ruboto
|
|
43
58
|
# EMXIF
|
44
59
|
|
45
60
|
script_name = options.delete(:script)
|
61
|
+
extras = options.delete(:extras)
|
46
62
|
raise "Unknown options: #{options}" unless options.empty?
|
47
63
|
|
48
64
|
if class_name.nil? && block_given?
|
@@ -50,6 +66,8 @@ module Ruboto
|
|
50
66
|
"#{java_class.name.split('::').last}_#{source_descriptor(block)[0].split('/').last.gsub(/[.-]+/, '_')}_#{source_descriptor(block)[1]}"
|
51
67
|
end
|
52
68
|
|
69
|
+
class_name = class_name.to_s
|
70
|
+
|
53
71
|
if Object.const_defined?(class_name)
|
54
72
|
Object.const_get(class_name).class_eval(&block) if block_given?
|
55
73
|
else
|
@@ -60,6 +78,7 @@ module Ruboto
|
|
60
78
|
i.putExtra(Ruboto::THEME_KEY, theme) if theme
|
61
79
|
i.putExtra(Ruboto::CLASS_NAME_KEY, class_name) if class_name
|
62
80
|
i.putExtra(Ruboto::SCRIPT_NAME_KEY, script_name) if script_name
|
81
|
+
extras.each { |k, v| i.putExtra(k.to_s, v) } if extras
|
63
82
|
startActivity i
|
64
83
|
self
|
65
84
|
end
|
data/lib/ruboto/commands/base.rb
CHANGED
@@ -103,10 +103,10 @@ module Ruboto
|
|
103
103
|
update_assets
|
104
104
|
update_ruboto true
|
105
105
|
update_icons true
|
106
|
-
update_classes nil,
|
106
|
+
update_classes nil, 'exclude'
|
107
107
|
update_jruby true if with_jruby
|
108
108
|
update_dx_jar true if with_jruby
|
109
|
-
update_core_classes '
|
109
|
+
update_core_classes 'exclude'
|
110
110
|
|
111
111
|
log_action('Generating the default Activity and script') do
|
112
112
|
generate_inheriting_file 'Activity', activity, package
|
@@ -351,7 +351,7 @@ module Ruboto
|
|
351
351
|
update_jruby force
|
352
352
|
update_manifest nil, nil, force
|
353
353
|
update_icons force
|
354
|
-
update_core_classes '
|
354
|
+
update_core_classes 'exclude'
|
355
355
|
update_bundle
|
356
356
|
when 'jruby' then
|
357
357
|
update_jruby(params['force'].value, true) || abort
|
@@ -394,12 +394,14 @@ module Ruboto
|
|
394
394
|
api_level = project_api_level
|
395
395
|
|
396
396
|
option('target', 't') {
|
397
|
-
|
397
|
+
extend Ruboto::Util::Emulator
|
398
|
+
description 'sets the target Android API level for the emulator'
|
399
|
+
examples Ruboto::Util::Emulator::API_LEVEL_TO_VERSION.keys.join(', ')
|
398
400
|
required unless api_level
|
399
401
|
argument :required
|
400
402
|
default(api_level) if api_level
|
401
403
|
cast {|t| t =~ /^(\d+)$/ ? "android-#$1" : t}
|
402
|
-
validate {|t| t =~ /^android
|
404
|
+
validate {|t| t =~ /^android-(\d+)$/ && sdk_level_name($1.to_i)}
|
403
405
|
}
|
404
406
|
|
405
407
|
def run
|
data/lib/ruboto/util/emulator.rb
CHANGED
@@ -6,8 +6,8 @@ module Ruboto
|
|
6
6
|
ON_WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i)
|
7
7
|
|
8
8
|
API_LEVEL_TO_VERSION = {
|
9
|
-
|
10
|
-
|
9
|
+
10 => '2.3.3', 11 => '3.0', 12 => '3.1', 13 => '3.2', 14 => '4.0',
|
10
|
+
15 => '4.0.3', 16 => '4.1.2', 17 => '4.2.2',
|
11
11
|
}
|
12
12
|
|
13
13
|
def sdk_level_name(sdk_level)
|
@@ -52,6 +52,7 @@ module Ruboto
|
|
52
52
|
puts 'No emulator is running.'
|
53
53
|
end
|
54
54
|
|
55
|
+
# FIXME(uwe): Change use of "killall" to use the Ruby Process API
|
55
56
|
loop do
|
56
57
|
`killall -0 #{emulator_cmd} 2> /dev/null`
|
57
58
|
if $? == 0
|
@@ -83,16 +84,18 @@ module Ruboto
|
|
83
84
|
abi_opt = '--abi armeabi'
|
84
85
|
end
|
85
86
|
|
86
|
-
|
87
|
+
avd_home = "#{ENV['HOME'].gsub('\\', '/')}/.android/avd/#{avd_name}.avd"
|
88
|
+
unless File.exists? avd_home
|
87
89
|
puts "Creating AVD #{avd_name}"
|
88
90
|
puts `echo n | android create avd -a -n #{avd_name} -t android-#{sdk_level} #{abi_opt} -c 64M -s HVGA`
|
89
91
|
if $? != 0
|
90
92
|
puts 'Failed to create AVD.'
|
91
93
|
exit 3
|
92
94
|
end
|
93
|
-
avd_config_file_name = "#{
|
95
|
+
avd_config_file_name = "#{avd_home}/config.ini"
|
94
96
|
old_avd_config = File.read(avd_config_file_name)
|
95
|
-
|
97
|
+
manifest_file = 'AndroidManifest.xml'
|
98
|
+
heap_size = (File.exists?(manifest_file) && File.read(manifest_file) =~ /largeHeap/) ? 256 : 48
|
96
99
|
new_avd_config = old_avd_config.gsub(/vm.heapSize=([0-9]*)/) { |m| p m; m.to_i < heap_size ? "vm.heapSize=#{heap_size}" : m }
|
97
100
|
File.write(avd_config_file_name, new_avd_config) if new_avd_config != old_avd_config
|
98
101
|
new_snapshot = true
|
@@ -163,7 +166,7 @@ module Ruboto
|
|
163
166
|
for i in 1 2 3 4 5 6 7 8 9 10 ; do
|
164
167
|
sleep 6
|
165
168
|
adb shell input keyevent 82 >/dev/null 2>&1
|
166
|
-
if [ "$?"
|
169
|
+
if [ "$?" = "0" ] ; then
|
167
170
|
set -e
|
168
171
|
adb shell input keyevent 82 >/dev/null 2>&1
|
169
172
|
adb shell input keyevent 4 >/dev/null 2>&1
|
data/lib/ruboto/util/setup.rb
CHANGED
@@ -46,7 +46,7 @@ module Ruboto
|
|
46
46
|
case RbConfig::CONFIG['host_os']
|
47
47
|
when /^darwin(.*)/ then
|
48
48
|
'macosx'
|
49
|
-
when
|
49
|
+
when /linux/ then
|
50
50
|
'linux'
|
51
51
|
when /^mswin32|windows(.*)/ then
|
52
52
|
'windows'
|
@@ -60,7 +60,7 @@ module Ruboto
|
|
60
60
|
if RbConfig::CONFIG['host_os'] =~ /^mswin32|windows(.*)/
|
61
61
|
'AppData/Local/Android/android-sdk'
|
62
62
|
else
|
63
|
-
"android-sdk-#{android_package_os_id}"
|
63
|
+
ENV['ANDROID_HOME'] ? ENV['ANDROID_HOME'] : File.join(File.expand_path('~'), "android-sdk-#{android_package_os_id}")
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -68,7 +68,7 @@ module Ruboto
|
|
68
68
|
case RbConfig::CONFIG['host_os']
|
69
69
|
when /^darwin(.*)/ then
|
70
70
|
'.profile'
|
71
|
-
when
|
71
|
+
when /linux/ then
|
72
72
|
'.bashrc'
|
73
73
|
when /^mswin32|windows(.*)/ then
|
74
74
|
'windows'
|
@@ -118,22 +118,22 @@ module Ruboto
|
|
118
118
|
|
119
119
|
def check_for_emulator
|
120
120
|
@emulator_loc = check_for('emulator', 'Android Emulator',
|
121
|
-
File.join(
|
121
|
+
File.join(android_package_directory, 'tools', 'emulator'))
|
122
122
|
end
|
123
123
|
|
124
124
|
def check_for_platform_tools
|
125
125
|
@adb_loc = check_for('adb', 'Android SDK Command adb',
|
126
|
-
File.join(
|
126
|
+
File.join(android_package_directory, 'platform-tools', 'adb'))
|
127
127
|
end
|
128
128
|
|
129
129
|
def check_for_build_tools
|
130
130
|
@dx_loc = check_for('dx', 'Android SDK Command dx',
|
131
|
-
Dir[File.join(
|
131
|
+
Dir[File.join(android_package_directory, 'build-tools', '*', 'dx')][-1])
|
132
132
|
end
|
133
133
|
|
134
134
|
def check_for_android_sdk
|
135
135
|
@android_loc = check_for('android', 'Android Package Installer',
|
136
|
-
File.join(
|
136
|
+
File.join(android_package_directory, 'tools', 'android'))
|
137
137
|
end
|
138
138
|
|
139
139
|
def check_for(cmd, pretty_name=nil, alt_dir=nil)
|
@@ -172,6 +172,7 @@ module Ruboto
|
|
172
172
|
install_java(accept_all) unless @java_loc && @javac_loc
|
173
173
|
install_ant(accept_all) unless @ant_loc
|
174
174
|
install_android_sdk(accept_all) unless @android_loc
|
175
|
+
check_all(api_levels)
|
175
176
|
install_android_tools(accept_all) unless @dx_loc && @adb_loc && @emulator_loc # build-tools, platform-tools and tools
|
176
177
|
if @android_loc
|
177
178
|
api_levels.each do |api_level|
|
@@ -183,7 +184,7 @@ module Ruboto
|
|
183
184
|
def install_java(accept_all)
|
184
185
|
case RbConfig::CONFIG['host_os']
|
185
186
|
when /^darwin(.*)/
|
186
|
-
when
|
187
|
+
when /linux/
|
187
188
|
when /^mswin32|windows(.*)/
|
188
189
|
# FIXME(uwe): Detect and warn if we are not "elevated" with adminstrator rights.
|
189
190
|
#set IS_ELEVATED=0
|
@@ -238,7 +239,7 @@ module Ruboto
|
|
238
239
|
def install_ant(accept_all)
|
239
240
|
case RbConfig::CONFIG['host_os']
|
240
241
|
when /^darwin(.*)/
|
241
|
-
when
|
242
|
+
when /linux/
|
242
243
|
when /^mswin32|windows(.*)/
|
243
244
|
# FIXME(uwe): Detect and warn if we are not "elevated" with adminstrator rights.
|
244
245
|
#set IS_ELEVATED=0
|
@@ -357,7 +358,7 @@ module Ruboto
|
|
357
358
|
system "wget http://dl.google.com/android/#{asdk_file_name}"
|
358
359
|
system "unzip #{'-o ' if accept_all}#{asdk_file_name}"
|
359
360
|
system "rm #{asdk_file_name}"
|
360
|
-
when
|
361
|
+
when /linux/
|
361
362
|
asdk_file_name = "android-sdk_r#{get_tools_version}-#{android_package_os_id}.tgz"
|
362
363
|
system "wget http://dl.google.com/android/#{asdk_file_name}"
|
363
364
|
system "tar -xzf #{asdk_file_name}"
|
@@ -389,10 +390,12 @@ module Ruboto
|
|
389
390
|
end
|
390
391
|
end
|
391
392
|
check_for_android_sdk
|
392
|
-
unless @android_loc
|
393
|
-
ENV['ANDROID_HOME'] = @android_loc.gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
|
393
|
+
unless @android_loc.nil?
|
394
|
+
ENV['ANDROID_HOME'] = (File.expand_path File.dirname(@android_loc)+"/..").gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
|
394
395
|
puts "Setting the ANDROID_HOME environment variable to #{ENV['ANDROID_HOME']}"
|
395
|
-
|
396
|
+
if RbConfig::CONFIG['host_os'] =~ /^mswin32|windows(.*)/
|
397
|
+
system %Q{setx ANDROID_HOME "#{ENV['ANDROID_HOME']}"}
|
398
|
+
end
|
396
399
|
@missing_paths << "#{File.dirname(@android_loc)}"
|
397
400
|
end
|
398
401
|
end
|
@@ -406,7 +409,7 @@ module Ruboto
|
|
406
409
|
a = STDIN.gets.chomp.upcase
|
407
410
|
end
|
408
411
|
if accept_all || a == 'Y' || a.empty?
|
409
|
-
update_cmd = "android --silent update sdk --no-ui --filter build-tools-#{get_tools_version('build-tool')},platform-tool,tool --force"
|
412
|
+
update_cmd = "android --silent update sdk --no-ui --filter build-tools-#{get_tools_version('build-tool')},platform-tool,tool -a --force"
|
410
413
|
update_sdk(update_cmd, accept_all)
|
411
414
|
check_for_build_tools
|
412
415
|
check_for_platform_tools
|
@@ -489,11 +492,6 @@ module Ruboto
|
|
489
492
|
config_file_name = File.expand_path("~/#{a.nil? || a.empty? ? path_setup_file : a}")
|
490
493
|
old_config = File.read(config_file_name)
|
491
494
|
new_config = old_config.dup
|
492
|
-
|
493
|
-
# FIXME(uwe): Remove for Ruboto > 0.13.0
|
494
|
-
new_config.gsub! /\n*# BEGIN Ruboto PATH setup\n.*?\n# END Ruboto PATH setup\n*/m, ''
|
495
|
-
# EMXIF
|
496
|
-
|
497
495
|
new_config.gsub! /\n*# BEGIN Ruboto setup\n.*?\n# END Ruboto setup\n*/m, ''
|
498
496
|
new_config << "\n\n# BEGIN Ruboto setup\n"
|
499
497
|
new_config << "source #{rubotorc}\n"
|