Skip to content

Commit 9dfff6e

Browse files
committed
Initial commit for SDK Updater
1 parent 1b9f9ba commit 9dfff6e

File tree

3 files changed

+354
-8
lines changed

3 files changed

+354
-8
lines changed

src/processing/mode/android/AndroidEditor.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,7 @@ public void actionPerformed(ActionEvent e) {
342342
item = new JMenuItem("Update SDK");
343343
item.addActionListener(new ActionListener() {
344344
public void actionPerformed(ActionEvent e) {
345-
File file = androidMode.getSDK().getAndroidTool();
346-
try {
347-
Runtime.getRuntime().exec(new String[] { file.getAbsolutePath(), "sdk" });
348-
} catch (IOException e1) {
349-
e1.printStackTrace();
350-
}
345+
new SDKUpdater();
351346
}
352347
});
353348
menu.add(item);

src/processing/mode/android/AndroidSDK.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ protected void checkDebugCertificate() {
242242
}
243243

244244

245-
public File getAndroidTool() {
246-
return androidTool;
245+
public File getToolsFolder() {
246+
return tools;
247247
}
248248

249249

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
package processing.mode.android;
2+
3+
import processing.app.Platform;
4+
5+
import javax.swing.*;
6+
import javax.swing.border.EmptyBorder;
7+
import javax.swing.table.DefaultTableModel;
8+
import java.awt.*;
9+
import java.awt.event.ActionEvent;
10+
import java.awt.event.ActionListener;
11+
import java.beans.PropertyChangeEvent;
12+
import java.beans.PropertyChangeListener;
13+
import java.io.BufferedReader;
14+
import java.io.File;
15+
import java.io.IOException;
16+
import java.io.InputStreamReader;
17+
import java.util.ArrayList;
18+
import java.util.Arrays;
19+
import java.util.HashMap;
20+
import java.util.Vector;
21+
22+
public class SDKUpdater extends JFrame implements PropertyChangeListener {
23+
24+
private HashMap<String, Boolean> requiredPackages;
25+
26+
private final Vector<String> columnsInstalled = new Vector<>(Arrays.asList("Path", "Version",
27+
"Description", "Location"));
28+
private final Class[] columnClassI = new Class[]{
29+
String.class, String.class, String.class, String.class, String.class
30+
};
31+
32+
private final Vector<String> columnsUpdates = new Vector<>(Arrays.asList("ID", "Installed", "Available"));
33+
private final Class[] columnClassU = new Class[]{
34+
String.class, String.class, String.class, String.class, String.class
35+
};
36+
37+
private static final String PROPERTY_CHANGE_QUERY = "query";
38+
39+
private AndroidSDK sdk;
40+
private File toolsFolder;
41+
private Vector<Vector<String>> updatesList;
42+
private Vector<Vector<String>> installedList;
43+
private QueryTask queryTask;
44+
private DownloadTask downloadTask;
45+
private boolean installFlag;
46+
47+
private DefaultTableModel modelInstalled;
48+
private DefaultTableModel modelUpdates;
49+
private JProgressBar progressBar;
50+
private JLabel status;
51+
private JButton actionButton;
52+
53+
public SDKUpdater() {
54+
super("SDK Updater");
55+
56+
requiredPackages = new HashMap<>();
57+
requiredPackages.put("build-tools", false);
58+
requiredPackages.put("platforms", false);
59+
requiredPackages.put("extras;android;m2repository", false);
60+
requiredPackages.put("extras;google;m2repository", false);
61+
requiredPackages.put("platform-tools", false);
62+
requiredPackages.put("tools", false);
63+
64+
try {
65+
sdk = AndroidSDK.load();
66+
toolsFolder = sdk.getToolsFolder();
67+
queryTask = new QueryTask();
68+
queryTask.addPropertyChangeListener(this);
69+
queryTask.execute();
70+
createLayout();
71+
} catch (IOException e) {
72+
e.printStackTrace();
73+
}
74+
}
75+
76+
@Override
77+
public void propertyChange(PropertyChangeEvent evt) {
78+
switch (evt.getPropertyName()) {
79+
case PROPERTY_CHANGE_QUERY:
80+
progressBar.setIndeterminate(false);
81+
if (requiredPackages.size() == 0) {
82+
if (updatesList.size() == 0) {
83+
status.setText("No updates available");
84+
status.setForeground(Color.GREEN);
85+
} else {
86+
actionButton.setVisible(true);
87+
status.setText("Update(s) found!");
88+
status.setForeground(Color.BLUE);
89+
}
90+
} else {
91+
status.setText("<html>Required packages missing.<br>Please install missing packages.</html>");
92+
status.setForeground(Color.RED);
93+
actionButton.setText("Install");
94+
actionButton.setVisible(true);
95+
installFlag = true;
96+
}
97+
break;
98+
}
99+
}
100+
101+
class QueryTask extends SwingWorker {
102+
@Override
103+
protected Object doInBackground() throws Exception {
104+
ArrayList<String> cmd = new ArrayList<>();
105+
String path = toolsFolder + File.separator + "bin" + File.separator;
106+
if (Platform.isWindows())
107+
path += "sdkmanager.bat";
108+
else
109+
path += "sdkmanager";
110+
cmd.add(path);
111+
cmd.add("--list");
112+
113+
ProcessBuilder process = new ProcessBuilder(cmd);
114+
Process p = process.start();
115+
try {
116+
BufferedReader reader =
117+
new BufferedReader(new InputStreamReader(p.getInputStream()));
118+
p.waitFor();
119+
120+
updatesList = new Vector<>();
121+
installedList = new Vector<>();
122+
String line;
123+
boolean skip = false, updates = false;
124+
while ((line = reader.readLine()) != null) {
125+
if (line.isEmpty())
126+
skip = !skip;
127+
128+
if (!skip && !line.startsWith("d")) { //Skip all available packages
129+
if (line.startsWith(" I"))
130+
updates = true;
131+
else if (!line.startsWith(" P") && !line.startsWith(" -") && !line.startsWith("I") &&
132+
!line.startsWith("A") && !line.isEmpty()) {
133+
String[] result = line.split("\\|");
134+
135+
// Remove matching packages; remaining packages haven't been installed
136+
String resKey = result[0].trim();
137+
if (requiredPackages.containsKey(resKey))
138+
requiredPackages.remove(resKey);
139+
else {
140+
for (String key : requiredPackages.keySet()) {
141+
if (resKey.startsWith(key)) {
142+
requiredPackages.remove(key);
143+
break;
144+
}
145+
}
146+
}
147+
148+
if (updates)
149+
updatesList.add(new Vector<>(Arrays.asList(result)));
150+
else
151+
installedList.add(new Vector<>(Arrays.asList(result)));
152+
}
153+
}
154+
}
155+
156+
firePropertyChange(PROPERTY_CHANGE_QUERY, "query", "SUCCESS");
157+
} catch (InterruptedException e) {
158+
p.destroy();
159+
}
160+
161+
return null;
162+
}
163+
164+
@Override
165+
protected void done() {
166+
super.done();
167+
168+
if (updatesList != null && installedList != null) {
169+
modelInstalled.setDataVector(installedList, columnsInstalled);
170+
modelUpdates.setDataVector(updatesList, columnsUpdates);
171+
172+
modelUpdates.fireTableDataChanged();
173+
modelInstalled.fireTableDataChanged();
174+
}
175+
}
176+
}
177+
178+
class DownloadTask extends SwingWorker {
179+
@Override
180+
protected Object doInBackground() throws Exception {
181+
ArrayList<String> cmd = new ArrayList<>();
182+
String path = toolsFolder + File.separator + "bin" + File.separator;
183+
if (Platform.isWindows())
184+
path += "sdkmanager.bat";
185+
else
186+
path += "sdkmanager";
187+
cmd.add(path);
188+
189+
if(installFlag) {
190+
191+
} else {
192+
cmd.add("--update");
193+
ProcessBuilder process = new ProcessBuilder(cmd);
194+
Process p = process.start();
195+
try {
196+
progressBar.setIndeterminate(true);
197+
p.waitFor();
198+
} catch (InterruptedException e) {
199+
p.destroy();
200+
}
201+
progressBar.setIndeterminate(false);
202+
}
203+
return null;
204+
}
205+
}
206+
207+
private void createLayout() {
208+
Container outer = getContentPane();
209+
outer.removeAll();
210+
211+
Box verticalBox = Box.createVerticalBox();
212+
verticalBox.setBorder(new EmptyBorder(13, 13, 13, 13));
213+
outer.add(verticalBox);
214+
215+
/* Packages panel */
216+
JPanel packagesPanel = new JPanel();
217+
packagesPanel.setBorder(BorderFactory.createTitledBorder(
218+
BorderFactory.createEtchedBorder(), "Packages"));
219+
220+
BoxLayout boxLayout = new BoxLayout(packagesPanel, BoxLayout.Y_AXIS);
221+
packagesPanel.setLayout(boxLayout);
222+
223+
/* Installed Packages panel */
224+
JPanel installedPanel = new JPanel();
225+
installedPanel.setBorder(BorderFactory.createTitledBorder(
226+
BorderFactory.createEtchedBorder(), "Installed"));
227+
228+
//Installed Packages table
229+
modelInstalled = new DefaultTableModel(15, columnClassI.length) {
230+
@Override
231+
public boolean isCellEditable(int row, int column) {
232+
return false;
233+
}
234+
235+
@Override
236+
public Class<?> getColumnClass(int columnIndex) {
237+
return columnClassI[columnIndex];
238+
}
239+
};
240+
JTable tInstalled = new JTable(modelInstalled) {
241+
@Override
242+
public String getColumnName(int column) {
243+
return columnsInstalled.get(column);
244+
}
245+
};
246+
tInstalled.setFillsViewportHeight(true);
247+
248+
tInstalled.setPreferredScrollableViewportSize(new Dimension(tInstalled.getPreferredSize().width,
249+
15 * tInstalled.getRowHeight()));
250+
installedPanel.add(new JScrollPane(tInstalled));
251+
252+
253+
/* Updates panel */
254+
JPanel updatesPanel = new JPanel();
255+
updatesPanel.setBorder(BorderFactory.createTitledBorder(
256+
BorderFactory.createEtchedBorder(), "Available Updates"));
257+
258+
//Updates table
259+
modelUpdates = new DefaultTableModel(5, columnClassU.length) {
260+
@Override
261+
public boolean isCellEditable(int row, int column) {
262+
return false;
263+
}
264+
265+
@Override
266+
public Class<?> getColumnClass(int columnIndex) {
267+
return columnClassU[columnIndex];
268+
}
269+
};
270+
JTable tUpdates = new JTable(modelUpdates) {
271+
@Override
272+
public String getColumnName(int column) {
273+
return columnsUpdates.get(column);
274+
}
275+
};
276+
tUpdates.setFillsViewportHeight(true);
277+
tUpdates.setPreferredScrollableViewportSize(new Dimension(tUpdates.getPreferredSize().width,
278+
5 * tUpdates.getRowHeight()));
279+
updatesPanel.add(new JScrollPane(tUpdates));
280+
281+
packagesPanel.add(installedPanel);
282+
packagesPanel.add(updatesPanel);
283+
284+
JPanel controlPanel = new JPanel();
285+
GridBagLayout gridBagLayout = new GridBagLayout();
286+
controlPanel.setLayout(gridBagLayout);
287+
288+
GridBagConstraints gbc = new GridBagConstraints();
289+
290+
status = new JLabel();
291+
status.setText("Querying");
292+
gbc.gridx = 0;
293+
gbc.gridy = 0;
294+
controlPanel.add(status, gbc);
295+
296+
progressBar = new JProgressBar();
297+
progressBar.setIndeterminate(true);
298+
gbc.gridx = 0;
299+
gbc.gridy = 1;
300+
gbc.weightx = 1.0;
301+
gbc.fill = GridBagConstraints.HORIZONTAL;
302+
controlPanel.add(progressBar, gbc);
303+
304+
actionButton = new JButton("Update");
305+
actionButton.addActionListener(new ActionListener() {
306+
public void actionPerformed(ActionEvent e) {
307+
downloadTask = new DownloadTask();
308+
downloadTask.execute();
309+
}
310+
});
311+
actionButton.setVisible(false);
312+
gbc.gridx = 1;
313+
gbc.gridy = 0;
314+
gbc.weightx = 0.0;
315+
gbc.fill = GridBagConstraints.HORIZONTAL;
316+
controlPanel.add(actionButton, gbc);
317+
318+
ActionListener disposer = new ActionListener() {
319+
public void actionPerformed(ActionEvent actionEvent) {
320+
cancelTasks();
321+
setVisible(false);
322+
}
323+
};
324+
325+
JButton closeButton = new JButton("Close");
326+
closeButton.addActionListener(disposer);
327+
closeButton.setEnabled(true);
328+
gbc.gridx = 1;
329+
gbc.gridy = 1;
330+
gbc.weightx = 0.0;
331+
gbc.fill = GridBagConstraints.HORIZONTAL;
332+
controlPanel.add(closeButton, gbc);
333+
334+
verticalBox.add(packagesPanel);
335+
verticalBox.add(controlPanel);
336+
pack();
337+
338+
JRootPane root = getRootPane();
339+
root.setDefaultButton(closeButton);
340+
processing.app.ui.Toolkit.registerWindowCloseKeys(root, disposer);
341+
processing.app.ui.Toolkit.setIcon(this);
342+
343+
setLocationRelativeTo(null);
344+
setResizable(false);
345+
setVisible(true);
346+
}
347+
348+
public void cancelTasks() {
349+
queryTask.cancel(true);
350+
}
351+
}

0 commit comments

Comments
 (0)