View Javadoc
1   package edu.jiangxin.apktoolbox.reverse;
2   
3   import edu.jiangxin.apktoolbox.swing.extend.plugin.PluginPanel;
4   import edu.jiangxin.apktoolbox.swing.extend.listener.SelectDirectoryListener;
5   import edu.jiangxin.apktoolbox.swing.extend.listener.SelectFileListener;
6   import edu.jiangxin.apktoolbox.utils.Constants;
7   import edu.jiangxin.apktoolbox.utils.Utils;
8   import org.apache.commons.io.FilenameUtils;
9   
10  import javax.swing.*;
11  import javax.swing.filechooser.FileFilter;
12  import java.awt.*;
13  import java.awt.event.ActionEvent;
14  import java.awt.event.ActionListener;
15  import java.io.File;
16  
17  public class ApktoolPanel extends PluginPanel {
18      public ApktoolPanel() throws HeadlessException {
19          super();
20      }
21  
22      @Override
23      public String getPluginFilename() {
24          return "apktool_2.9.2.jar";
25      }
26  
27      @Override
28      public void initUI() {
29          BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
30          setLayout(boxLayout);
31  
32          JTabbedPane categoryTabbedPane = new JTabbedPane();
33          add(categoryTabbedPane);
34  
35          JPanel decodeCategoryPanel = new ApktoolDecodePanel();
36          JPanel rebuildCategoryPanel = new ApktoolRebuildPanel();
37  
38          categoryTabbedPane.addTab("Decode", null, decodeCategoryPanel, "Decode the APK file");
39          categoryTabbedPane.setSelectedIndex(0);
40          categoryTabbedPane.addTab("Rebuild", null, rebuildCategoryPanel, "Rebuild the APK file");
41      }
42  
43      abstract class ApktoolPanelBase extends JPanel {
44          protected JPanel srcPanel;
45  
46          protected JPanel targetPanel;
47  
48          protected JPanel optionPanel;
49  
50          protected JPanel operationPanel;
51  
52          protected ApktoolPanelBase() throws HeadlessException {
53              super();
54              initUI();
55          }
56  
57          private void initUI() {
58              BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
59              setLayout(boxLayout);
60  
61              createSrcPanel();
62              add(srcPanel);
63              add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
64  
65              createTargetPanel();
66              add(targetPanel);
67              add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
68  
69              createOptionPanel();
70              add(optionPanel);
71              add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
72  
73              createOperationPanel();
74              add(operationPanel);
75          }
76  
77          protected void createSrcPanel() {
78              srcPanel = new JPanel();
79              srcPanel.setLayout(new BoxLayout(srcPanel, BoxLayout.X_AXIS));
80          }
81  
82          protected void createTargetPanel() {
83              targetPanel = new JPanel();
84              targetPanel.setLayout(new BoxLayout(targetPanel, BoxLayout.X_AXIS));
85          }
86  
87          protected void createOptionPanel() {
88              optionPanel = new JPanel();
89              optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.X_AXIS));
90          }
91  
92          protected void createOperationPanel() {
93              operationPanel = new JPanel();
94              operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
95          }
96      }
97  
98      class ApktoolDecodePanel extends ApktoolPanelBase {
99          private JTextField srcTextField;
100 
101         private JTextField targetTextField;
102 
103         private JCheckBox resourceIgnoreCheckBox;
104 
105         private JCheckBox overrideCheckBox;
106 
107         public ApktoolDecodePanel() throws HeadlessException {
108             super();
109         }
110 
111         @Override
112         public void createSrcPanel() {
113             super.createSrcPanel();
114 
115             srcTextField = new JTextField();
116             srcTextField.setText(conf.getString("apktool.decode.src.file"));
117 
118             JButton srcButton = new JButton(bundle.getString("choose.file.button"));
119             srcButton.addActionListener(new SelectFileListener("select a file", srcTextField));
120 
121             srcPanel.add(srcTextField);
122             srcPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
123             srcPanel.add(srcButton);
124         }
125 
126         @Override
127         public void createTargetPanel() {
128             super.createTargetPanel();
129 
130             targetTextField = new JTextField();
131             targetTextField.setText(conf.getString("apktool.decode.target.dir"));
132 
133             JButton targetButton = new JButton(bundle.getString("save.dir.button"));
134             targetButton.addActionListener(new SelectDirectoryListener("Save To", targetTextField));
135 
136             targetPanel.add(targetTextField);
137             targetPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
138             targetPanel.add(targetButton);
139         }
140 
141         @Override
142         public void createOptionPanel() {
143             super.createOptionPanel();
144 
145             resourceIgnoreCheckBox = new JCheckBox("Ignore res");
146             resourceIgnoreCheckBox.setSelected(false);
147             optionPanel.add(resourceIgnoreCheckBox);
148 
149             overrideCheckBox = new JCheckBox("Override");
150             overrideCheckBox.setSelected(true);
151             optionPanel.add(overrideCheckBox);
152         }
153 
154         @Override
155         public void createOperationPanel() {
156             super.createOperationPanel();
157 
158             JButton decodeButton = new JButton("Decode");
159             decodeButton.addActionListener(new ApktoolDecodePanel.DecodeButtonActionListener());
160 
161             operationPanel.add(decodeButton);
162         }
163 
164         private final class DecodeButtonActionListener implements ActionListener {
165             @Override
166             public void actionPerformed(ActionEvent e) {
167                 String srcPath = checkAndGetFileContent(srcTextField, "apktool.decode.src.file", "Source file is invalid");
168                 if (srcPath == null) {
169                     return;
170                 }
171 
172                 String targetPath = checkAndGetDirContent(targetTextField, "apktool.decode.target.dir", "Target directory is invalid");
173                 if (targetPath == null) {
174                     return;
175                 }
176 
177                 String srcBaseName = FilenameUtils.getBaseName(srcPath);
178                 StringBuilder sb = new StringBuilder();
179                 sb.append(ApktoolPanel.this.getPluginStartupCmd()).append(" d ")
180                         .append(srcPath).append(" -o ").append(targetPath).append(File.separator).append(srcBaseName);
181                 if (resourceIgnoreCheckBox.isSelected()) {
182                     sb.append(" -r");
183                 }
184                 if (overrideCheckBox.isSelected()) {
185                     sb.append(" -f");
186                 }
187                 Utils.blockedExecutor(sb.toString());
188             }
189         }
190     }
191 
192     class ApktoolRebuildPanel extends ApktoolPanelBase {
193         private JTextField srcTextField;
194 
195         private JTextField targetTextField;
196 
197         private JCheckBox signAPK;
198 
199         public ApktoolRebuildPanel() throws HeadlessException {
200             super();
201         }
202 
203         @Override
204         public void createSrcPanel() {
205             super.createSrcPanel();
206 
207             srcTextField = new JTextField();
208             srcTextField.setText(conf.getString("apktool.rebuild.src.dir"));
209 
210             JButton srcButton = new JButton(bundle.getString("choose.dir.button"));
211             srcButton.addActionListener(new SelectDirectoryListener("Select Directory", srcTextField));
212 
213             srcPanel.add(srcTextField);
214             srcPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
215             srcPanel.add(srcButton);
216         }
217 
218         @Override
219         public void createTargetPanel() {
220             super.createTargetPanel();
221 
222             targetTextField = new JTextField();
223             targetTextField.setText(conf.getString("apktool.rebuild.target.file"));
224 
225             JButton targetButton = new JButton(bundle.getString("save.file.button"));
226             targetButton.addActionListener(new SelectFileListener("save to", targetTextField, new ApktoolRebuildPanel.ApkFileFilter()));
227 
228             targetPanel.add(targetTextField);
229             targetPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
230             targetPanel.add(targetButton);
231         }
232 
233         @Override
234         public void createOptionPanel() {
235             super.createOptionPanel();
236 
237             signAPK = new JCheckBox("sign APK");
238             signAPK.setSelected(false);
239             optionPanel.add(signAPK);
240         }
241 
242         @Override
243         public void createOperationPanel() {
244             super.createOperationPanel();
245 
246             JButton rebuildButton = new JButton("Rebuild");
247             rebuildButton.addActionListener(new ApktoolRebuildPanel.RebuildButtonActionListener());
248             operationPanel.add(rebuildButton);
249         }
250 
251         private final class RebuildButtonActionListener implements ActionListener {
252             @Override
253             public void actionPerformed(ActionEvent e) {
254                 String srcPath = checkAndGetDirContent(srcTextField, "apktool.rebuild.src.dir", "Source directory is invalid");
255                 if (srcPath == null) {
256                     return;
257                 }
258 
259                 String targetPath = checkAndGetNewFileContent(targetTextField, "apktool.rebuild.target.file", "Target file is invalid");
260                 if (targetPath == null) {
261                     return;
262                 }
263 
264                 StringBuilder sb = new StringBuilder();
265                 sb.append(ApktoolPanel.this.getPluginStartupCmd()).append(" b ")
266                         .append(srcPath).append(" -o ").append(targetPath);
267                 Utils.blockedExecutor(sb.toString());
268                 if (signAPK.isSelected()) {
269                     sb = new StringBuilder();
270                     sb.append(ApktoolPanel.this.getPluginStartupCmd())
271                             .append(" -keystore ").append(Utils.getToolsPath()).append(File.separator)
272                             .append("debug.keystore").append(" -alias androiddebugkey -pswd android ")
273                             .append(targetPath);
274                     Utils.blockedExecutor(sb.toString());
275                 }
276             }
277         }
278 
279         private final class ApkFileFilter extends FileFilter {
280 
281             @Override
282             public boolean accept(File f) {
283                 String nameString = f.getName();
284                 return nameString.toLowerCase().endsWith(".apk");
285             }
286 
287             @Override
288             public String getDescription() {
289                 return "*.apk";
290             }
291         }
292     }
293 }
294