ruboto 0.13.0 → 0.14.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.
- 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"
|