• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jiangxincode / ApkToolBoxGUI / #620

29 Feb 2024 03:11PM UTC coverage: 3.224% (-0.005%) from 3.229%
#620

push

jiangxincode
optimize the monkey test panel

0 of 241 new or added lines in 1 file covered. (0.0%)

20 existing lines in 1 file now uncovered.

240 of 7445 relevant lines covered (3.22%)

0.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/jiangxin/apktoolbox/android/monkey/MonkeyPanel.java
1
package edu.jiangxin.apktoolbox.android.monkey;
2

3
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
4
import edu.jiangxin.apktoolbox.swing.extend.NumberPlainDocument;
5
import edu.jiangxin.apktoolbox.utils.Constants;
6
import edu.jiangxin.apktoolbox.utils.DateUtils;
7
import org.apache.commons.io.IOUtils;
8

9
import javax.swing.*;
10
import java.awt.*;
11
import java.awt.event.ItemEvent;
12
import java.io.*;
13
import java.nio.charset.StandardCharsets;
14
import java.util.ArrayList;
15
import java.util.List;
16
import java.util.Objects;
17

18
/**
19
 * @author jiangxin
20
 * @author 2019-04-12
21
 *
22
 */
23
public class MonkeyPanel extends EasyPanel {
×
24

25
    @Serial
26
    private static final long serialVersionUID = 1L;
27
    
28
    private static final String LOG_NAME = "java_monkey_log";
29

30
    private static final String HOUR = "时";
31
    private static final String MINUTE = "分";
32
    private static final String SECOND = "秒";
33

34
    private static final String CMD_PS_A = "adb -s ";
35
    private static final String CMD_PS_B = " shell ps";
36
    private static final String CMD_KILL_A = "adb -s ";
37
    private static final String CMD_KILL_B = " shell kill ";
38

39
    private static final String MONKEY = "com.android.commands.monkey";
40

41
    private static final String IGNORE_CRASHES = " --ignore-crashes";
42
    private static final String IGNORE_TIMEOUTS = " --ignore-timeouts";
43
    private static final String MONITOR_NATIVE_CRASHES = " --monitor-native-crashes";
44
    private static final String IGNORE_SECURITY_EXCEPTIONS = " --ignore-security-exceptions";
45
    private static final String KILL_PROCESS_AFTER_ERROR = " --kill-process-after-error";
46
    private static final String WAIT_DBG = " --wait-dbg";
47
    private static final String HPROF = " --hprof";
48

49
    private static final String LEVEL_0 = " -v ";
50
    private static final String LEVEL_1 = " -v -v ";
51
    private static final String LEVEL_2 = " -v -v -v ";
52

53
    private static final String TRANSACTIONCOUNT = "9999";
54

55
    /**
56
     * 设备列表不能为空!
57
     */
58
    private static final String MSG4 = "设备列表不能为空!请[刷新]!";
59

60
    /**
61
     * 应用程序不能为空!
62
     */
63
    private static final String MSG5 = "应用程序不能为空!请选其他设备!";
64

65
    /**
66
     * 事件间隔或时间数量不能为空!
67
     */
68
    private static final String MSG2 = "事件间隔或时间数量不能为空!";
69

70
    /**
71
     * 日志保存路径不能为空!
72
     */
73
    private static final String MSG6 = "日志保存路径不能为空!";
74

75
    Thread threadTimeType = null;
×
76
    Process monkeyProcess = null;
×
77

NEW
78
    JComboBox<String> comboBoxDevices = new JComboBox<>();
×
79
    JButton refreshButton = new JButton("刷新");
×
80

81
    JButton logPathButton = new JButton("选择路径");
×
NEW
82
    JButton executeButton = new JButton("运行命令");
×
83

84
    JButton resetButton = new JButton("重置页面");
×
85
    JButton interruptButton = new JButton("终止运行");
×
86

UNCOV
87
    JLabel labelHour = new JLabel();
×
88
    JLabel labelMinute = new JLabel();
×
89
    JLabel labelSecond = new JLabel();
×
90
    JTextField textMillisecond = new JTextField(30);
×
91
    JTextField textTime = new JTextField(30);
×
92
    JTextField textLogPath = new JTextField(90);
×
93

NEW
94
    JComboBox<String> comboBoxProgram = new JComboBox<>();
×
NEW
95
    JComboBox<String> comboBoxTime = new JComboBox<>();
×
96

97
    /**
98
     * --dbg-no-events:初始化启动的activity,但是不产生任何事件
99
     */
100
    JCheckBox checkBoxDbgNoEvents = new JCheckBox("初始化启动的activity,但是不产生任何事件");
×
101

102
    /**
103
     * --hprof:指定该项后在事件序列发送前后会立即生成分析报告(一般建议指定该项)
104
     */
105
    JCheckBox checkBoxHprof = new JCheckBox("在事件序列发送前后会立即生成分析报告");
×
106

107
    /**
108
     * --ignore-crashes:忽略崩溃
109
     */
110
    JCheckBox checkBoxCrashes = new JCheckBox("忽略崩溃", true);
×
111

112
    /**
113
     * --ignore-timeouts:忽略超时
114
     */
115
    JCheckBox checkBoxTimeouts = new JCheckBox("忽略超时", true);
×
116

117
    /**
118
     * --monitor-native-crashes:跟踪本地方法的崩溃问题
119
     */
120
    JCheckBox checkBoxNativeCrashes = new JCheckBox("跟踪本地方法的崩溃问题", true);
×
121

122
    /**
123
     * --ignore-security-exceptions:忽略安全异常
124
     */
125
    JCheckBox checkBoxExceptions = new JCheckBox("忽略安全异常", true);
×
126

127
    /**
128
     * --kill-process-after-error:发生错误后直接杀掉进程
129
     */
130
    JCheckBox checkBoxKill = new JCheckBox("发生错误后直接杀掉进程");
×
131

132
    /**
133
     * --wait-dbg:知道连接了调试器才执行monkey测试
134
     */
135
    JCheckBox checkBoxWaitDbg = new JCheckBox("停止Monkey执行,直到有调试器与其连接");
×
136

137
    ButtonGroup group = new ButtonGroup();
×
138

139
    /**
140
     * 缺省值
141
     */
142
    JRadioButton radioButton0 = new JRadioButton("基本信息");
×
143

144
    /**
145
     * 比较详细
146
     */
147
    JRadioButton radioButton1 = new JRadioButton("比较详细");
×
148

149
    /**
150
     * 非常详细(默认选中)
151
     */
152
    JRadioButton radioButton2 = new JRadioButton("非常详细", true);
×
153

154
    String dbgNoEvents = "";
×
155
    String hprof = "";
×
156
    String ignoreCrashes = "";
×
157
    String ignoreTimeouts = "";
×
158
    String monitorNativeCrashes = "";
×
159
    String ignoreSecurityExceptions = "";
×
160
    String killProcessAfterError = "";
×
161
    String waitDbg = "";
×
162

163
    String logLevel = "";
×
164
    ArrayList<String> list;
165
    int flag = 0;
×
166
    String[] monkeyCmd = null;
×
167

168
    @Override
169
    public void initUI() {
170
        setPreferredSize(new Dimension(Constants.DEFAULT_PANEL_WIDTH, Constants.DEFAULT_PANEL_HEIGHT));
×
NEW
171
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
×
172

NEW
173
        JPanel devicesPanel = new JPanel();
×
NEW
174
        devicesPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
175
        initDevices(devicesPanel);
×
NEW
176
        add(devicesPanel);
×
177

NEW
178
        JPanel programPanel = new JPanel();
×
NEW
179
        programPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
180
        initProgram(programPanel);
×
NEW
181
        add(programPanel);
×
182

NEW
183
        JPanel restrainConditionPanel = new JPanel();
×
NEW
184
        restrainConditionPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
185
        initRestrainCondition(restrainConditionPanel);
×
NEW
186
        add(restrainConditionPanel);
×
187

NEW
188
        JPanel eventIntervalPanel = new JPanel();
×
NEW
189
        eventIntervalPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
190
        initEventInterval(eventIntervalPanel);
×
NEW
191
        add(eventIntervalPanel);
×
192

NEW
193
        JPanel runTimePanel = new JPanel();
×
NEW
194
        runTimePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
195
        initRunTime(runTimePanel);
×
NEW
196
        add(runTimePanel);
×
197

NEW
198
        JPanel logLevelPanel = new JPanel();
×
NEW
199
        logLevelPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
200
        initLogLevel(logLevelPanel);
×
NEW
201
        add(logLevelPanel);
×
202

NEW
203
        JPanel logPathPanel = new JPanel();
×
NEW
204
        logPathPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
205
        initLogPath(logPathPanel);
×
NEW
206
        add(logPathPanel);
×
207

NEW
208
        JPanel operationPanel = new JPanel();
×
NEW
209
        operationPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
NEW
210
        initOperation(operationPanel);
×
NEW
211
        add(operationPanel);
×
UNCOV
212
    }
×
213

214
    private void initDevices(JPanel panel) {
NEW
215
        JLabel labelDevices = new JLabel("设备列表");
×
NEW
216
        labelDevices.setPreferredSize(new Dimension(60, 25));
×
NEW
217
        comboBoxDevices.setPreferredSize(new Dimension(240, 25));
×
NEW
218
        refreshButton.setPreferredSize(new Dimension(60, 25));
×
219

NEW
220
        panel.add(labelDevices);
×
NEW
221
        panel.add(comboBoxDevices);
×
NEW
222
        panel.add(refreshButton);
×
223

NEW
224
        refreshButton.addActionListener(e -> {
×
NEW
225
            comboBoxDevices.removeAllItems();
×
NEW
226
            List<String> devices = getDevices();
×
NEW
227
            for (String device : devices) {
×
NEW
228
                comboBoxDevices.addItem(device);
×
NEW
229
            }
×
NEW
230
        });
×
NEW
231
    }
×
232

233
    private void initProgram(JPanel panel) {
NEW
234
        JLabel labelProgram = new JLabel("应用程序");
×
NEW
235
        labelProgram.setPreferredSize(new Dimension(60, 25));
×
NEW
236
        comboBoxProgram.setPreferredSize(new Dimension(240, 25));
×
237
        comboBoxProgram.setEditable(true);
×
238
        comboBoxProgram.setSelectedItem("com.shinow.*");
×
239

NEW
240
        panel.add(labelProgram);
×
NEW
241
        panel.add(comboBoxProgram);
×
242

NEW
243
        comboBoxDevices.addActionListener(e -> {
×
NEW
244
            comboBoxProgram.removeAllItems();
×
NEW
245
            comboBoxProgram.setSelectedItem("com.shinow.*");
×
NEW
246
            List<String> programs = getApplication(comboBoxDevices.getSelectedItem().toString());
×
NEW
247
            for (String program : programs) {
×
NEW
248
                comboBoxProgram.addItem(program);
×
UNCOV
249
            }
×
250

UNCOV
251
        });
×
UNCOV
252
    }
×
253

254
    private void initRestrainCondition(JPanel panel) {
NEW
255
        JLabel labelRestrain = new JLabel("约束条件");
×
NEW
256
        labelRestrain.setPreferredSize(new Dimension(60, 25));
×
NEW
257
        checkBoxCrashes.setPreferredSize(new Dimension(100, 25));
×
NEW
258
        checkBoxTimeouts.setPreferredSize(new Dimension(100, 25));
×
NEW
259
        checkBoxExceptions.setPreferredSize(new Dimension(110, 25));
×
NEW
260
        checkBoxNativeCrashes.setPreferredSize(new Dimension(180, 25));
×
NEW
261
        checkBoxKill.setPreferredSize(new Dimension(180, 25));
×
NEW
262
        checkBoxWaitDbg.setPreferredSize(new Dimension(280, 25));
×
NEW
263
        checkBoxHprof.setPreferredSize(new Dimension(280, 25));
×
264

NEW
265
        panel.add(labelRestrain);
×
NEW
266
        panel.add(checkBoxCrashes);
×
NEW
267
        panel.add(checkBoxTimeouts);
×
NEW
268
        panel.add(checkBoxExceptions);
×
NEW
269
        panel.add(checkBoxNativeCrashes);
×
NEW
270
        panel.add(checkBoxKill);
×
NEW
271
        panel.add(checkBoxWaitDbg);
×
NEW
272
        panel.add(checkBoxHprof);
×
273

NEW
274
        checkBoxCrashes.addItemListener(e -> {
×
NEW
275
            if (e.getStateChange() == ItemEvent.SELECTED) {
×
NEW
276
                ignoreCrashes = IGNORE_CRASHES;
×
277
            } else {
NEW
278
                ignoreCrashes = "";
×
279
            }
UNCOV
280
        });
×
281

NEW
282
        checkBoxTimeouts.addItemListener(e -> {
×
NEW
283
            if (e.getStateChange() == ItemEvent.SELECTED) {
×
NEW
284
                ignoreTimeouts = IGNORE_TIMEOUTS;
×
285
            } else {
NEW
286
                ignoreTimeouts = "";
×
287
            }
UNCOV
288
        });
×
289

NEW
290
        checkBoxExceptions.addItemListener(e -> {
×
NEW
291
            if (e.getStateChange() == ItemEvent.SELECTED) {
×
NEW
292
                ignoreSecurityExceptions = IGNORE_SECURITY_EXCEPTIONS;
×
293
            } else {
NEW
294
                ignoreSecurityExceptions = "";
×
295
            }
UNCOV
296
        });
×
297

NEW
298
        checkBoxNativeCrashes.addItemListener(e -> {
×
NEW
299
            if (e.getStateChange() == ItemEvent.SELECTED) {
×
NEW
300
                monitorNativeCrashes = MONITOR_NATIVE_CRASHES;
×
301
            } else {
NEW
302
                monitorNativeCrashes = "";
×
303
            }
UNCOV
304
        });
×
305

306
    }
×
307

308
    private void initEventInterval(JPanel panel) {
NEW
309
        JLabel labelSpace = new JLabel("事件间隔");
×
NEW
310
        labelSpace.setPreferredSize(new Dimension(60, 25));
×
NEW
311
        textMillisecond.setPreferredSize(new Dimension(150, 25));
×
312
        textMillisecond.setDocument(new NumberPlainDocument(7));
×
313
        textMillisecond.setText("500");
×
NEW
314
        JLabel labelMillisecond = new JLabel("毫秒");
×
NEW
315
        labelMillisecond.setPreferredSize(new Dimension(40, 25));
×
316

NEW
317
        panel.add(labelSpace);
×
NEW
318
        panel.add(textMillisecond);
×
NEW
319
        panel.add(labelMillisecond);
×
NEW
320
    }
×
321

322
    private void initRunTime(JPanel panel) {
NEW
323
        JLabel labelTime = new JLabel("运行时长");
×
NEW
324
        labelTime.setPreferredSize(new Dimension(60, 25));
×
NEW
325
        textTime.setPreferredSize(new Dimension(150, 25));
×
326
        textTime.setDocument(new NumberPlainDocument(7));
×
327
        textTime.setText("1");
×
NEW
328
        comboBoxTime.setPreferredSize(new Dimension(60, 25));
×
329
        comboBoxTime.addItem(HOUR);
×
330
        comboBoxTime.addItem(MINUTE);
×
331
        comboBoxTime.addItem(SECOND);
×
332

NEW
333
        labelHour.setPreferredSize(new Dimension(50, 25));
×
NEW
334
        labelMinute.setPreferredSize(new Dimension(50, 25));
×
NEW
335
        labelSecond.setPreferredSize(new Dimension(50, 25));
×
336

NEW
337
        panel.add(labelTime);
×
NEW
338
        panel.add(textTime);
×
NEW
339
        panel.add(comboBoxTime);
×
340

NEW
341
        panel.add(labelHour);
×
NEW
342
        panel.add(labelMinute);
×
NEW
343
        panel.add(labelSecond);
×
UNCOV
344
    }
×
345

346
    private void initLogLevel(JPanel panel) {
NEW
347
        JLabel labelLogLevel = new JLabel("日志级别");
×
NEW
348
        labelLogLevel.setPreferredSize(new Dimension(60, 25));
×
349

350
        group.add(radioButton0);
×
351
        group.add(radioButton1);
×
352
        group.add(radioButton2);
×
353

NEW
354
        radioButton0.setPreferredSize(new Dimension(80, 25));
×
NEW
355
        radioButton1.setPreferredSize(new Dimension(80, 25));
×
NEW
356
        radioButton2.setPreferredSize(new Dimension(80, 25));
×
357

NEW
358
        panel.add(labelLogLevel);
×
NEW
359
        panel.add(radioButton0);
×
NEW
360
        panel.add(radioButton1);
×
NEW
361
        panel.add(radioButton2);
×
NEW
362
    }
×
363

364
    private void initLogPath(JPanel panel) {
NEW
365
        logPathButton.setPreferredSize(new Dimension(100, 25));
×
NEW
366
        textLogPath.setColumns(60);
×
367
        textLogPath.setEditable(false);
×
368
        textLogPath.setText("D:");
×
369

NEW
370
        panel.add(logPathButton);
×
NEW
371
        panel.add(textLogPath);
×
372

NEW
373
        logPathButton.addActionListener(e -> {
×
NEW
374
            if (e.getSource() == logPathButton) {
×
NEW
375
                JFileChooser fileChooser = new JFileChooser();
×
NEW
376
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
×
NEW
377
                int intRetVal = fileChooser.showOpenDialog(new Label());
×
NEW
378
                if (intRetVal == JFileChooser.APPROVE_OPTION) {
×
NEW
379
                    textLogPath.setText(fileChooser.getSelectedFile().getPath());
×
380
                }
381
            }
UNCOV
382
        });
×
UNCOV
383
    }
×
384

385
    private void initOperation(JPanel panel) {
NEW
386
        executeButton.setPreferredSize(new Dimension(100, 25));
×
NEW
387
        resetButton.setPreferredSize(new Dimension(100, 25));
×
NEW
388
        interruptButton.setPreferredSize(new Dimension(100, 25));
×
389

NEW
390
        panel.add(executeButton);
×
NEW
391
        panel.add(resetButton);
×
NEW
392
        panel.add(interruptButton);
×
393

394
        interruptButton.setEnabled(false);
×
395

NEW
396
        executeButton.addActionListener(e -> execute());
×
397

NEW
398
        resetButton.addActionListener(e -> reset());
×
399

NEW
400
        interruptButton.addActionListener(e -> interrupt());
×
401

402
    }
×
403

404
    private void execute() {
NEW
405
        ignoreCrashes = checkBoxCrashes.isSelected() ? IGNORE_CRASHES : "";
×
NEW
406
        ignoreTimeouts = checkBoxTimeouts.isSelected() ? IGNORE_TIMEOUTS : "";
×
NEW
407
        monitorNativeCrashes = checkBoxNativeCrashes.isSelected() ? MONITOR_NATIVE_CRASHES : "";
×
NEW
408
        ignoreSecurityExceptions = checkBoxExceptions.isSelected() ? IGNORE_SECURITY_EXCEPTIONS : "";
×
NEW
409
        hprof = checkBoxHprof.isSelected() ? HPROF : "";
×
NEW
410
        killProcessAfterError = checkBoxKill.isSelected() ? KILL_PROCESS_AFTER_ERROR : "";
×
NEW
411
        waitDbg = checkBoxWaitDbg.isSelected() ? WAIT_DBG : "";
×
412

413
        // 判断设备列表和应用程序是否为空
NEW
414
        if (comboBoxDevices.getItemCount() == 0) {
×
NEW
415
            new MyDialog(MSG4).setVisible(true);
×
NEW
416
            refreshButton.requestFocus();
×
NEW
417
            return;
×
418
        }
NEW
419
        if (comboBoxProgram.getItemCount() == 0) {
×
NEW
420
            new MyDialog(MSG5).setVisible(true);
×
NEW
421
            return;
×
422
        }
423
        // 判断事件间隔和运行时长是否为空
NEW
424
        if (textMillisecond.getText().length() == 0) {
×
NEW
425
            new MyDialog(MSG2).setVisible(true);
×
NEW
426
            textMillisecond.requestFocus();
×
NEW
427
            return;
×
428
        }
NEW
429
        if (textTime.getText().length() == 0) {
×
NEW
430
            new MyDialog(MSG2).setVisible(true);
×
NEW
431
            textTime.requestFocus();
×
NEW
432
            return;
×
433
        }
NEW
434
        if (textLogPath.getText().length() == 0) {
×
NEW
435
            new MyDialog(MSG6).setVisible(true);
×
NEW
436
            logPathButton.requestFocus();
×
NEW
437
            return;
×
438
        }
439

440
        // 获取日志级别
NEW
441
        if (radioButton0.isSelected()) {
×
NEW
442
            logLevel = LEVEL_0;
×
NEW
443
        } else if (radioButton1.isSelected()) {
×
NEW
444
            logLevel = LEVEL_1;
×
NEW
445
        } else if (radioButton2.isSelected()) {
×
NEW
446
            logLevel = LEVEL_2;
×
447
        }
NEW
448
        String logFile = textLogPath.getText() + "\\" + LOG_NAME + DateUtils.getCurrentDateString() + ".txt";
×
449

NEW
450
        monkeyCmd = new String[] { "cmd.exe", "/C",
×
NEW
451
                "adb -s " + comboBoxDevices.getSelectedItem() + " shell monkey -p "
×
NEW
452
                        + comboBoxProgram.getSelectedItem() + "" + ignoreCrashes + "" + ignoreTimeouts + ""
×
453
                        + ignoreSecurityExceptions + "" + monitorNativeCrashes + " --throttle "
NEW
454
                        + textMillisecond.getText() + "" + logLevel + "" + TRANSACTIONCOUNT + " > " + logFile };
×
455

NEW
456
        logger.info("Monkey:" + monkeyCmd[2]);
×
457

NEW
458
        flag = 0;
×
459

460
        try {
NEW
461
            monkeyProcess = Runtime.getRuntime().exec(monkeyCmd);
×
NEW
462
        } catch (Exception ex) {
×
NEW
463
            logger.error("Exception", ex);
×
NEW
464
        }
×
465

NEW
466
        executeButton.setEnabled(false);
×
NEW
467
        resetButton.setEnabled(false);
×
NEW
468
        interruptButton.setEnabled(true);
×
469

470
        // 倒计时文本
NEW
471
        labelHour.setVisible(true);
×
NEW
472
        labelMinute.setVisible(true);
×
NEW
473
        labelSecond.setVisible(true);
×
474

475
        // 获取时间类型
NEW
476
        String timeType = (String) comboBoxTime.getSelectedItem();
×
NEW
477
        long time = Long.parseLong(textTime.getText());
×
NEW
478
        if (Objects.equals(timeType, HOUR)) {
×
NEW
479
            time *= 3600;
×
NEW
480
        } else if (Objects.equals(timeType, MINUTE)) {
×
NEW
481
            time *= 60;
×
482
        }
NEW
483
        threadTimeType = new Thread(new CountdownRunnable(time));
×
NEW
484
        threadTimeType.start();
×
NEW
485
    }
×
486

487
    private void reset() {
488
        // 重置约束条件
NEW
489
        checkBoxCrashes.setSelected(true);
×
NEW
490
        checkBoxTimeouts.setSelected(true);
×
NEW
491
        checkBoxExceptions.setSelected(true);
×
NEW
492
        checkBoxNativeCrashes.setSelected(true);
×
493
        // 重置日志级别
NEW
494
        radioButton0.setSelected(false);
×
NEW
495
        radioButton1.setSelected(false);
×
NEW
496
        radioButton2.setSelected(true);
×
497
        // 重置事件间隔
NEW
498
        textMillisecond.setText("500");
×
499
        // 重置运行时长
NEW
500
        textTime.setText("1");
×
NEW
501
    }
×
502

503
    private void interrupt() {
504
        // 杀掉Monkey执行进程
NEW
505
        interruptThread();
×
NEW
506
        executeButton.setEnabled(true);
×
NEW
507
        resetButton.setEnabled(true);
×
NEW
508
        interruptButton.setEnabled(false);
×
UNCOV
509
    }
×
510

511
    /**
512
     * 中断Monkey命令
513
     */
514
    public void interruptThread() {
515

516
        logger.info("中断Monkey命令--开始");
×
517

518
        String[] cmd1 = new String[] { "cmd.exe", "/c", CMD_PS_A + comboBoxDevices.getSelectedItem() + CMD_PS_B };
×
519
        executeCommand(cmd1, MONKEY);
×
520

521
        List<String> listPid = list;
×
522
        logger.info("获取的中断Monkey进程数量:" + listPid.size());
×
523

524
        String[] cmd2 = null;
×
525
        String pid = "";
×
NEW
526
        for (String s : listPid) {
×
NEW
527
            pid = s;
×
NEW
528
            cmd2 = new String[]{"cmd.exe", "/c", CMD_KILL_A + comboBoxDevices.getSelectedItem() + CMD_KILL_B + pid};
×
UNCOV
529
            executeCommand(cmd2, MONKEY);
×
UNCOV
530
        }
×
531

532
        flag = 1;
×
533

534
        monkeyProcess.destroy();
×
535

536
        labelHour.setVisible(false);
×
537
        labelMinute.setVisible(false);
×
538
        labelSecond.setVisible(false);
×
539

540
        logger.info("中断Monkey命令--结束");
×
541

542
    }
×
543

544
    private List<String> getDevices() {
545
        List<String> devices = new ArrayList<>();
×
546
        logger.info("get device list start");
×
547
        Process process = null;
×
548
        try {
549
            process = Runtime.getRuntime().exec("adb devices");
×
550
        } catch (IOException e) {
×
551
            logger.error("exec command failed: " + e.getMessage());
×
552
        }
×
553
        if (process == null) {
×
554
            logger.error("process is null");
×
555
            return devices;
×
556
        }
NEW
557
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
×
558
            String line;
559
            while ((line = reader.readLine()) != null) {
×
560
                if (line.contains("device") && !line.contains("List of")) {
×
561
                    line = line.substring(0, line.length() - 7);
×
562
                    logger.info("device name: " + line);
×
563
                    devices.add(line);
×
564
                }
565
            }
566
        } catch (IOException e) {
×
567
            logger.error("read failed: " + e.getMessage());
×
568
        } finally {
569
            IOUtils.closeQuietly(process.getOutputStream());
×
570
            IOUtils.closeQuietly(process.getErrorStream());
×
571
            IOUtils.closeQuietly(process.getInputStream());
×
572
        }
573
        logger.info("get device list end");
×
574
        return devices;
×
575
    }
576

577
    private List<String> getApplication(String device) {
578
        List<String> apps = new ArrayList<>();
×
579
        logger.info("get application list start");
×
580
        Process process = null;
×
581
        try {
582
            process = Runtime.getRuntime().exec(new String[]{"adb", "-s", device, "shell", "pm", "list", "packages"});
×
583
        } catch (IOException e) {
×
584
            logger.error("exec command failed: " + e.getMessage());
×
585
        }
×
586
        if (process == null) {
×
587
            logger.error("process is null");
×
588
            return apps;
×
589
        }
NEW
590
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
×
591
            String line;
592
            while ((line = reader.readLine()) != null) {
×
593
                if (line.contains("package:")) {
×
594
                    logger.info("application name:" + line);
×
595
                    apps.add(line.replace("package:", ""));
×
596
                }
597
            }
598
        } catch (IOException e) {
×
599
            logger.error("read failed: " + e.getMessage());
×
600
        } finally {
601
            IOUtils.closeQuietly(process.getOutputStream());
×
602
            IOUtils.closeQuietly(process.getErrorStream());
×
603
            IOUtils.closeQuietly(process.getInputStream());
×
604
        }
605
        logger.info("get application list end");
×
606
        return apps;
×
607
    }
608

609
    private void executeCommand(String[] cmd, String keyValue) {
610
        logger.info("exec cmd start");
×
611
        list = new ArrayList<>();
×
612
        Process process = null;
×
613
        try {
614
            process = Runtime.getRuntime().exec(cmd);
×
615
        } catch (IOException e) {
×
616
            logger.error("exec command failed: " + e.getMessage());
×
617
        }
×
618
        if (process == null) {
×
619
            logger.error("process is null");
×
620
            return;
×
621
        }
NEW
622
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
×
623
            String line;
624
            while ((line = reader.readLine()) != null) {
×
NEW
625
                if (line.contains(keyValue)) {
×
626
                    line = line.replace(" ", ":");
×
627
                    System.out.println("[" + keyValue + "][" + line + "]");
×
628
                    String[] str = line.split(":");
×
629
                    System.out.println(str.length);
×
630
                    for (int i = 1; i < str.length; i++) {
×
631
                        if (str[i].length() > 0) {
×
632
                            logger.info("Pid: " + str[i]);
×
633
                            list.add(str[i]);
×
634
                            break;
×
635
                        }
636
                    }
637
                }
×
638
            }
639
        } catch (IOException e) {
×
640
            logger.error("read failed: " + e.getMessage());
×
641
        } finally {
642
            IOUtils.closeQuietly(process.getOutputStream());
×
643
            IOUtils.closeQuietly(process.getErrorStream());
×
644
            IOUtils.closeQuietly(process.getInputStream());
×
645
        }
646
        logger.info("exec cmd end");
×
647
    }
×
648

649
    /**
650
     * 倒计时
651
     * 
652
     */
653
    class CountdownRunnable implements Runnable {
654
        private long times;
655

656
        public CountdownRunnable(long times) {
×
657
            this.times = times;
×
658
        }
×
659

660
        @Override
661
        public void run() {
662
            // 自定义倒计时时间
NEW
663
            long time = times;
×
664
            long hour = 0;
×
665
            long minute = 0;
×
666
            long seconds = 0;
×
667

668
            if (time >= 0) {
×
669
                for (int i = 0; i <= time; i++) {
×
670
                    // 监控Monkey命令
NEW
671
                    monitorMonkey(time, MONKEY);
×
672
                    // 监控Monkey命令操作的App
NEW
673
                    monitorApp(time, comboBoxProgram.getSelectedItem().toString());
×
674
                    // 判断标识,是否中断操作
675
                    System.out.println("flag==1?Interrupt:Continue:" + flag);
×
676
                    if (flag == 1) {
×
677
                        break;
×
678
                    }
679
                    hour = time / 3600;
×
680
                    minute = (time - hour * 3600) / 60;
×
681
                    seconds = time - hour * 3600 - minute * 60;
×
682
                    labelHour.setText(hour + HOUR);
×
683
                    labelMinute.setText(minute + MINUTE);
×
684
                    labelSecond.setText(seconds + SECOND);
×
685
                    try {
686
                        Thread.sleep(1000);
×
NEW
687
                    } catch (InterruptedException e) {
×
NEW
688
                        logger.error("InterruptedException {}", e.getMessage());
×
NEW
689
                        Thread.currentThread().interrupt();
×
UNCOV
690
                    }
×
691
                    // 正常结束
692
                    if (time == 0) {
×
693
                        Thread.currentThread().interrupt();
×
694
                        interruptThread();
×
NEW
695
                        executeButton.setEnabled(true);
×
696
                        resetButton.setEnabled(true);
×
697
                        interruptButton.setEnabled(false);
×
698
                    }
UNCOV
699
                    i--;
×
700
                    time--;
×
701
                }
702
                if (flag == 1) {
×
703
                    Thread.currentThread().interrupt();
×
704
                    threadTimeType.interrupt();
×
NEW
705
                    executeButton.setEnabled(true);
×
706
                    resetButton.setEnabled(true);
×
707
                    interruptButton.setEnabled(false);
×
708
                }
709
            }
710
        }
×
711

712
        /**
713
         * 间隔60秒监控一次运行monkey命令是否为运行状态,或已关闭
714
         * 
715
         * @param time     当前剩余执行时间
716
         * @param keyValue Monkey命令的进程名称
717
         */
718
        private void monitorMonkey(long time, String keyValue) {
719
            if ((time - 1) % 120 == 0) {
×
720
                logger.info("监控[" + keyValue + "]线程是否执行完毕---开始");
×
721
                logger.info("每60秒监听一次,此时time的值:" + (time - 1));
×
722
                String[] cmd = new String[] { "cmd.exe", "/c",
×
723
                        CMD_PS_A + comboBoxDevices.getSelectedItem() + CMD_PS_B };
×
724
                logger.info("当前命令:" + cmd[2]);
×
725
                executeCommand(cmd, keyValue);
×
726
                logger.info("当前线程数:" + list.size());
×
727
                if (list.size() == 0) {
×
728
                    String log = textLogPath.getText();
×
729
                    System.out.println(textLogPath.getText());
×
730
                    String getDate = DateUtils.getCurrentDateString();
×
731
                    // 日志文件路径
732
                    String logFile = log.substring(0, log.indexOf("java_monkey_log")) + LOG_NAME + getDate + ".txt";
×
733
                    textLogPath.setText(logFile);
×
734
                    System.out.println("monkeyCmd[2];" + monkeyCmd[2]);
×
735
                    monkeyCmd[2] = monkeyCmd[2].substring(0, monkeyCmd[2].indexOf("java_monkey_log"))
×
736
                            + "java_monkey_log" + getDate + ".txt";
737
                    logger.info("Monkey命令已经停止,再次执行");
×
738
                    logger.info("monkeyCmd[2];" + monkeyCmd[2]);
×
739
                    String[] monkeyCommand = new String[] { "cmd.exe", "/c", monkeyCmd[2] };
×
740
                    logger.info("执行");
×
741
                    // 再次执行
742
                    try {
743
                        monkeyProcess = Runtime.getRuntime().exec(monkeyCommand);
×
744
                    } catch (Exception e) {
×
745
                        logger.error("Exception", e);
×
746
                    }
×
747
                }
748
                logger.info("监控[" + keyValue + "]线程是否执行完毕---结束");
×
749
            }
750
        }
×
751

752
        /**
753
         * 间隔60秒监控一次运行app是否是启动状态,或崩溃掉
754
         * 
755
         * @param time     当前剩余执行时间
756
         * @param keyValue App的进程名称
757
         */
758
        private void monitorApp(long time, String keyValue) {
759
            if ((time - 1) % 120 == 0) {
×
760
                logger.info("监控[" + keyValue + "]线程是否执行完毕---开始");
×
761
                logger.info("每60秒监听一次,此时time的值:" + (time - 1));
×
762
                String[] cmd = new String[] { "cmd.exe", "/c",
×
763
                        CMD_PS_A + comboBoxDevices.getSelectedItem() + CMD_PS_B };
×
764
                logger.info("当前命令:" + cmd[2]);
×
765
                executeCommand(cmd, keyValue);
×
766
                logger.info("当前线程数:" + list.size());
×
767
                if (list.size() == 0) {
×
768
                    logger.info("[" + keyValue + "]已经关闭或崩溃,无法继续执行Monkey,退出系统");
×
769
                    logger.info("监控[" + keyValue + "]线程是否执行完毕---结束");
×
770
                    // 杀掉Monkey执行进程
771
                    interruptThread();
×
772
                    // System.gc();
773
                }
774
                logger.info("监控[" + keyValue + "]线程是否执行完毕---结束");
×
775
            }
776
        }
×
777
    }
778

779
    static class MyDialog extends JDialog {
780

781
        @Serial
782
        private static final long serialVersionUID = 1L;
783

784
        MyDialog(String msg3) {
NEW
785
            super((Frame)null, "提示", true);
×
NEW
786
            setSize(320, 180);
×
NEW
787
            Container container = getContentPane();
×
UNCOV
788
            container.setLayout(null);
×
UNCOV
789
            JLabel jl = new JLabel(msg3);
×
790
            jl.setBounds(70, 1, 200, 100);
×
791
            JButton jbb = new JButton("确    定");
×
792
            jbb.setBounds(97, 80, 100, 25);
×
793
            container.add(jl);
×
794
            container.add(jbb);
×
795

796
            // 设置位置
797
            int w = (Toolkit.getDefaultToolkit().getScreenSize().width - 320) / 2;
×
798
            int h = (Toolkit.getDefaultToolkit().getScreenSize().height - 180) / 2;
×
799

NEW
800
            setLocation(w, h);
×
801

NEW
802
            jbb.addActionListener(e -> dispose());
×
NEW
803
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
×
UNCOV
804
        }
×
805
    }
806
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc