Skip to content

Commit b9ea3d3

Browse files
committed
Download emulator images separately
1 parent a043b73 commit b9ea3d3

File tree

6 files changed

+467
-94
lines changed

6 files changed

+467
-94
lines changed

src/processing/mode/android/AVD.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import processing.app.exec.ProcessResult;
2828
import processing.core.PApplet;
2929

30+
import java.awt.Frame;
3031
import java.io.IOException;
3132
import java.util.ArrayList;
3233
import java.util.HashMap;
@@ -87,7 +88,7 @@ public class AVD {
8788

8889
/** Default virtual wear device used by Processing. */
8990
static public final AVD wearAVD =
90-
new AVD("Wear-Processing-0" + Base.getRevision(),
91+
new AVD("Processing-Wear-0" + Base.getRevision(),
9192
AndroidBuild.target_platform, "android-wear", WEAR_SKIN);
9293

9394
public AVD(final String name, final String target,
@@ -283,16 +284,20 @@ protected boolean create(final AndroidSDK sdk) throws IOException {
283284

284285

285286

286-
static public boolean ensureProperAVD(final AndroidSDK sdk) {
287+
static public boolean ensureProperAVD(final Frame window, final AndroidMode mode,
288+
final AndroidSDK sdk) {
287289
try {
288290

289291
if (AndroidBuild.appComponent == AndroidBuild.WATCHFACE) {
290292
if (wearAVD.exists(sdk)) {
291293
return true;
292294
}
293295
if (wearAVD.badness()) {
294-
Messages.showWarningTiered("Android Error", AVD_LOAD_PRIMARY, AVD_LOAD_SECONDARY, null);
295-
return false;
296+
boolean res = AndroidSDK.locateSysImage(window, mode, true);
297+
if (!res) {
298+
Messages.showWarningTiered("Android Error", AVD_LOAD_PRIMARY, AVD_LOAD_SECONDARY, null);
299+
return false;
300+
}
296301
}
297302
if (wearAVD.create(sdk)) {
298303
return true;
@@ -302,8 +307,11 @@ static public boolean ensureProperAVD(final AndroidSDK sdk) {
302307
return true;
303308
}
304309
if (defaultAVD.badness()) {
305-
Messages.showWarningTiered("Android Error", AVD_LOAD_PRIMARY, AVD_LOAD_SECONDARY, null);
306-
return false;
310+
boolean res = AndroidSDK.locateSysImage(window, mode, false);
311+
if (!res) {
312+
Messages.showWarningTiered("Android Error", AVD_LOAD_PRIMARY, AVD_LOAD_SECONDARY, null);
313+
return false;
314+
}
307315
}
308316
if (defaultAVD.create(sdk)) {
309317
return true;

src/processing/mode/android/AndroidEditor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ public void run() {
572572
startIndeterminate();
573573
prepareRun();
574574
try {
575-
androidMode.handleRunEmulator(sketch, AndroidEditor.this);
575+
androidMode.handleRunEmulator(sketch, AndroidEditor.this, AndroidEditor.this);
576576
} catch (SketchException e) {
577577
statusError(e);
578578
} catch (IOException e) {

src/processing/mode/android/AndroidMode.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,16 @@ static public String getDateStamp(long stamp) {
256256
// runtime.launch(false);
257257
// }
258258
// }
259-
public void handleRunEmulator(Sketch sketch, RunnerListener listener) throws SketchException, IOException {
259+
public void handleRunEmulator(Sketch sketch, AndroidEditor editor,
260+
RunnerListener listener) throws SketchException, IOException {
260261
listener.startIndeterminate();
261262
listener.statusNotice("Starting build...");
262263
AndroidBuild build = new AndroidBuild(sketch, this);
263264

264265
listener.statusNotice("Building Android project...");
265266
build.build("debug");
266267

267-
boolean avd = AVD.ensureProperAVD(sdk);
268+
boolean avd = AVD.ensureProperAVD(editor, this, sdk);
268269
if (!avd) {
269270
SketchException se =
270271
new SketchException("Could not create a virtual device for the emulator.");

src/processing/mode/android/AndroidSDK.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,22 @@ class AndroidSDK {
6464
"the command line tools from <a href=\"" + DOWNLOAD_URL + "\">here</a>. Make sure to install<br>" +
6565
"the SDK platform for API " + AndroidBuild.target_sdk + ".";
6666

67+
private static final String ANDROID_SYS_IMAGE_PRIMARY =
68+
"Download emulator?";
69+
70+
private static final String ANDROID_SYS_IMAGE_SECONDARY =
71+
"The emulator does not appear to be installed, <br>" +
72+
"Do you want Processing to download and install it now? <br>" +
73+
"Otherwise, you will need to do it through SDK manager.";
74+
75+
private static final String ANDROID_SYS_IMAGE_WEAR_PRIMARY =
76+
"Download watch emulator?";
77+
78+
private static final String ANDROID_SYS_IMAGE_WEAR_SECONDARY =
79+
"The watch emulator does not appear to be installed, <br>" +
80+
"Do you want Processing to download and install it now? <br>" +
81+
"Otherwise, you will need to do it through SDK manager.";
82+
6783
private static final String SELECT_ANDROID_SDK_FOLDER =
6884
"Choose the location of the Android SDK";
6985

@@ -284,6 +300,19 @@ static public AndroidSDK locate(final Frame window, final AndroidMode androidMod
284300
throw new CancelException("User canceled attempt to find SDK");
285301
}
286302
}
303+
304+
static public boolean locateSysImage(final Frame window,
305+
final AndroidMode androidMode, boolean wear)
306+
throws BadSDKException, CancelException, IOException {
307+
final int result = showDownloadSysImageDialog(window, wear);
308+
if (result == JOptionPane.YES_OPTION) {
309+
return downloadSysImage(window, androidMode, wear);
310+
} else if (result == JOptionPane.NO_OPTION) {
311+
return false;
312+
} else {
313+
return false;
314+
}
315+
}
287316

288317
static public AndroidSDK download(final Frame editor, final AndroidMode androidMode)
289318
throws BadSDKException, CancelException {
@@ -299,6 +328,22 @@ static public AndroidSDK download(final Frame editor, final AndroidMode androidM
299328
}
300329
return sdk;
301330
}
331+
332+
static public boolean downloadSysImage(final Frame editor,
333+
final AndroidMode androidMode, final boolean wear)
334+
throws BadSDKException, CancelException {
335+
final SysImageDownloader downloader = new SysImageDownloader(editor, androidMode, wear);
336+
downloader.run(); // This call blocks until the SDK download complete, or user cancels.
337+
338+
if (downloader.cancelled()) {
339+
throw new CancelException("User canceled emulator download");
340+
}
341+
boolean res = downloader.getResult();
342+
if (!res) {
343+
throw new BadSDKException("Emulator could not be downloaded");
344+
}
345+
return res;
346+
}
302347

303348
static public int showLocateDialog(Frame editor) {
304349
// Pane formatting adapted from the Quaqua guide
@@ -335,6 +380,43 @@ static public int showLocateDialog(Frame editor) {
335380
return JOptionPane.CLOSED_OPTION;
336381
}
337382
}
383+
384+
385+
static public int showDownloadSysImageDialog(Frame editor, boolean wear) {
386+
String msg1 = wear ? ANDROID_SYS_IMAGE_WEAR_PRIMARY : ANDROID_SYS_IMAGE_PRIMARY;
387+
String msg2 = wear ? ANDROID_SYS_IMAGE_WEAR_SECONDARY : ANDROID_SYS_IMAGE_SECONDARY;
388+
389+
JOptionPane pane =
390+
new JOptionPane("<html> " +
391+
"<head> <style type=\"text/css\">"+
392+
"b { font: 13pt \"Lucida Grande\" }"+
393+
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px; width: 300px }"+
394+
"</style> </head>" +
395+
"<b>" + msg1 + "</b>" +
396+
"<p>" + msg2 + "</p>",
397+
JOptionPane.QUESTION_MESSAGE);
398+
399+
String[] options = new String[] { "Yes", "No" };
400+
pane.setOptions(options);
401+
402+
// highlight the safest option ala apple hig
403+
pane.setInitialValue(options[0]);
404+
405+
JDialog dialog = pane.createDialog(editor, null);
406+
dialog.setTitle("");
407+
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
408+
dialog.setVisible(true);
409+
410+
Object result = pane.getValue();
411+
if (result == options[0]) {
412+
return JOptionPane.YES_OPTION;
413+
} else if (result == options[1]) {
414+
return JOptionPane.NO_OPTION;
415+
} else {
416+
return JOptionPane.CLOSED_OPTION;
417+
}
418+
}
419+
338420

339421
// this was banished from Base because it encourages bad practice.
340422
// TODO figure out a better way to handle the above.

src/processing/mode/android/SDKDownloader.java

Lines changed: 2 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,6 @@ public class SDKDownloader extends JDialog implements PropertyChangeListener {
5252
private static final String URL_REPOSITORY = "https://dl-ssl.google.com/android/repository/repository-11.xml";
5353
private static final String URL_REPOSITORY_FOLDER = "http://dl-ssl.google.com/android/repository/";
5454
private static final String URL_USB_DRIVER = "https://dl-ssl.google.com//android/repository/latest_usb_driver_windows.zip";
55-
private static final String URL_SYS_IMAGES = "https://dl-ssl.google.com/android/repository/sys-img/android/sys-img.xml";
56-
private static final String URL_SYS_IMAGES_FOLDER = "http://dl-ssl.google.com/android/repository/sys-img/android/";
57-
private static final String URL_SYS_IMAGES_WEAR = "https://dl-ssl.google.com/android/repository/sys-img/android-wear/sys-img.xml";
58-
private static final String URL_SYS_IMAGES_WEAR_FOLDER = "https://dl-ssl.google.com/android/repository/sys-img/android-wear/";
59-
private static final String SYSTEM_IMAGE = "Intel x86 Atom System Image";
60-
private static final String SYSTEM_IMAGE_WEAR = "Android Wear Intel x86 Atom System Image";
6155

6256
private static final String PROPERTY_CHANGE_EVENT_TOTAL = "total";
6357
private static final String PROPERTY_CHANGE_EVENT_DOWNLOADED = "downloaded";
@@ -77,9 +71,7 @@ public class SDKDownloader extends JDialog implements PropertyChangeListener {
7771
class SDKUrlHolder {
7872
public String platformVersion;
7973
public String platformToolsUrl, buildToolsUrl, platformUrl, toolsUrl;
80-
public String sysImgUrl, sysImgTag, sysImgWearUrl, sysImgWearTag;
8174
public String platformToolsFilename, buildToolsFilename, platformFilename, toolsFilename;
82-
public String sysImgFilename, sysImgWearFilename;
8375
public int totalSize = 0;
8476
}
8577

@@ -90,11 +82,6 @@ class SDKDownloadTask extends SwingWorker<Object, Object> {
9082

9183
@Override
9284
protected Object doInBackground() throws Exception {
93-
94-
95-
// File modeDirectory = new File(folder, getTypeName());
96-
//
97-
// File modeFolder = new File(Base.getSketchbookModesFolder() + "/AndroidMode");
9885

9986
File modeFolder = mode.getFolder();
10087

@@ -105,8 +92,6 @@ protected Object doInBackground() throws Exception {
10592
if (!platformsFolder.exists()) platformsFolder.mkdir();
10693
File buildToolsFolder = new File(sdkFolder, "build-tools");
10794
if (!buildToolsFolder.exists()) buildToolsFolder.mkdir();
108-
File sysImgFolder = new File(sdkFolder, "system-images");
109-
if (!sysImgFolder.exists()) sysImgFolder.mkdir();
11095
File extrasFolder = new File(sdkFolder, "extras");
11196
if(!extrasFolder.exists()) extrasFolder.mkdir();
11297

@@ -115,8 +100,7 @@ protected Object doInBackground() throws Exception {
115100
if (!tempFolder.exists()) tempFolder.mkdir();
116101

117102
try {
118-
SDKUrlHolder downloadUrls = getDownloadUrls(URL_REPOSITORY,
119-
URL_SYS_IMAGES, URL_SYS_IMAGES_WEAR, Platform.getName());
103+
SDKUrlHolder downloadUrls = getDownloadUrls(URL_REPOSITORY, Platform.getName());
120104
firePropertyChange(PROPERTY_CHANGE_EVENT_TOTAL, 0, downloadUrls.totalSize);
121105
totalSize = downloadUrls.totalSize;
122106

@@ -136,22 +120,6 @@ protected Object doInBackground() throws Exception {
136120
File downloadedPlatform = new File(tempFolder, downloadUrls.platformFilename);
137121
downloadAndUnpack(downloadUrls.platformUrl, downloadedPlatform, platformsFolder, false);
138122

139-
// system images
140-
File downloadedSysImg = new File(tempFolder, downloadUrls.sysImgFilename);
141-
File tmp = new File(sysImgFolder, "android-" + AndroidBuild.target_sdk);
142-
if (!tmp.exists()) tmp.mkdir();
143-
File sysImgFinalFolder = new File(tmp, downloadUrls.sysImgTag);
144-
if (!sysImgFinalFolder.exists()) sysImgFinalFolder.mkdir();
145-
downloadAndUnpack(downloadUrls.sysImgUrl, downloadedSysImg, sysImgFinalFolder, false);
146-
147-
// wear system images
148-
File downloadedSysImgWear = new File(tempFolder, downloadUrls.sysImgWearFilename);
149-
tmp = new File(sysImgFolder, "android-" + AndroidBuild.target_sdk);
150-
if (!tmp.exists()) tmp.mkdir();
151-
File sysImgWearFinalFolder = new File(tmp, downloadUrls.sysImgWearTag);
152-
if (!sysImgWearFinalFolder.exists()) sysImgWearFinalFolder.mkdir();
153-
downloadAndUnpack(downloadUrls.sysImgWearUrl, downloadedSysImgWear, sysImgWearFinalFolder, false);
154-
155123
// usb driver
156124
if (Platform.isWindows()) {
157125
File usbDriverFolder = new File(extrasFolder, "google");
@@ -235,9 +203,7 @@ private void downloadAndUnpack(String urlString, File saveTo,
235203
AndroidMode.extractFolder(saveTo, unpackTo, setExec);
236204
}
237205

238-
private SDKUrlHolder getDownloadUrls(String repositoryUrl,
239-
String repositorySysImgUrlString, String repositorySysImgWearUrlString,
240-
String requiredHostOs)
206+
private SDKUrlHolder getDownloadUrls(String repositoryUrl, String requiredHostOs)
241207
throws ParserConfigurationException, IOException, SAXException {
242208
SDKUrlHolder urlHolder = new SDKUrlHolder();
243209

@@ -312,55 +278,6 @@ private SDKUrlHolder getDownloadUrls(String repositoryUrl,
312278
}
313279
}
314280

315-
// system image
316-
Document docSysImg = db.parse(new URL(repositorySysImgUrlString).openStream());
317-
NodeList sysImgList = docSysImg.getElementsByTagName("sdk:system-image");
318-
for (int i = 0; i < sysImgList.getLength(); i++) {
319-
Node img = sysImgList.item(i);
320-
NodeList level = ((Element) img).getElementsByTagName("sdk:api-level");
321-
NodeList desc = ((Element) img).getElementsByTagName("sdk:description");
322-
NodeList codename = ((Element) img).getElementsByTagName("sdk:codename");
323-
// Only considering nodes without a codename, which correspond to the platform
324-
// pre-releases.
325-
if (level.item(0).getTextContent().equals(AndroidBuild.target_sdk) &&
326-
desc.item(0).getTextContent().equals(SYSTEM_IMAGE) &&
327-
codename.item(0) == null) {
328-
NodeList tag = ((Element) img).getElementsByTagName("sdk:tag-id");
329-
urlHolder.sysImgTag = tag.item(0).getTextContent();
330-
archiveListItem = ((Element) img).getElementsByTagName("sdk:archives").item(0);
331-
Node archiveItem = ((Element) archiveListItem).getElementsByTagName("sdk:archive").item(0);
332-
urlHolder.sysImgFilename = ((Element) archiveItem).getElementsByTagName("sdk:url").item(0).getTextContent();
333-
urlHolder.sysImgUrl = URL_SYS_IMAGES_FOLDER + urlHolder.sysImgFilename;
334-
urlHolder.totalSize += Integer.parseInt(((Element) archiveItem).getElementsByTagName("sdk:size").item(0).getTextContent());
335-
break;
336-
}
337-
}
338-
339-
// wear system image
340-
Document docSysImgWear = db.parse(new URL(repositorySysImgWearUrlString).openStream());
341-
NodeList sysImgWearList = docSysImgWear.getElementsByTagName("sdk:system-image");
342-
for (int i = 0; i < sysImgWearList.getLength(); i++) {
343-
Node img = sysImgWearList.item(i);
344-
NodeList level = ((Element) img).getElementsByTagName("sdk:api-level");
345-
NodeList desc = ((Element) img).getElementsByTagName("sdk:description");
346-
NodeList codename = ((Element) img).getElementsByTagName("sdk:codename");
347-
// Only considering nodes without a codename, which correspond to the platform
348-
// pre-releases.
349-
if (level.item(0).getTextContent().equals(AndroidBuild.target_sdk) &&
350-
desc.item(0).getTextContent().equals(SYSTEM_IMAGE_WEAR) &&
351-
codename.item(0) == null) {
352-
NodeList tag = ((Element) img).getElementsByTagName("sdk:tag-id");
353-
urlHolder.sysImgWearTag = tag.item(0).getTextContent();
354-
archiveListItem = ((Element) img).getElementsByTagName("sdk:archives").item(0);
355-
Node archiveItem = ((Element) archiveListItem).getElementsByTagName("sdk:archive").item(0);
356-
urlHolder.sysImgWearFilename = ((Element) archiveItem).getElementsByTagName("sdk:url").item(0).getTextContent();
357-
urlHolder.sysImgWearUrl = URL_SYS_IMAGES_WEAR_FOLDER + urlHolder.sysImgWearFilename;
358-
urlHolder.totalSize += Integer.parseInt(((Element) archiveItem).getElementsByTagName("sdk:size").item(0).getTextContent());
359-
break;
360-
}
361-
}
362-
363-
364281
return urlHolder;
365282
}
366283
}

0 commit comments

Comments
 (0)