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

jiangxincode / ApkToolBoxGUI / #1166

06 Sep 2025 11:06AM UTC coverage: 2.891%. Remained the same
#1166

push

jiangxincode
[PMD issues]Fix PMD issues: UnnecessaryFullyQualifiedName

3 of 27 new or added lines in 11 files covered. (11.11%)

1 existing line in 1 file now uncovered.

248 of 8579 relevant lines covered (2.89%)

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.io.*;
12
import java.nio.charset.StandardCharsets;
13
import java.util.ArrayList;
14
import java.util.List;
15
import java.util.Objects;
16

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

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

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

33
    private static final String CMD = "cmd.exe";
34

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

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

42
    private static final String TRANSACTIONCOUNT = "9999";
43

44
    /**
45
     * 设备列表不能为空!
46
     */
47
    private static final String MSG4 = "设备列表不能为空!请[刷新]!";
48

49
    /**
50
     * 应用程序不能为空!
51
     */
52
    private static final String MSG5 = "应用程序不能为空!请选其他设备!";
53

54
    /**
55
     * 事件间隔或时间数量不能为空!
56
     */
57
    private static final String MSG2 = "事件间隔或时间数量不能为空!";
58

59
    /**
60
     * 日志保存路径不能为空!
61
     */
62
    private static final String MSG6 = "日志保存路径不能为空!";
63

64
    Thread threadTimeType = null;
×
65
    Process monkeyProcess = null;
×
66

67
    JComboBox<String> comboBoxDevices = new JComboBox<>();
×
68
    JButton refreshButton = new JButton("刷新");
×
69

70
    JButton logPathButton = new JButton("选择路径");
×
71
    JButton executeButton = new JButton("运行命令");
×
72

73
    JButton resetButton = new JButton("重置页面");
×
74
    JButton interruptButton = new JButton("终止运行");
×
75

76
    JLabel labelHour = new JLabel();
×
77
    JLabel labelMinute = new JLabel();
×
78
    JLabel labelSecond = new JLabel();
×
79
    JTextField textMillisecond = new JTextField(30);
×
80
    JTextField textTime = new JTextField(30);
×
81
    JTextField textLogPath = new JTextField(90);
×
82

83
    JComboBox<String> comboBoxProgram = new JComboBox<>();
×
84
    JComboBox<String> comboBoxTime = new JComboBox<>();
×
85

86
    /**
87
     * --dbg-no-events:初始化启动的activity,但是不产生任何事件
88
     */
89
    JCheckBox checkBoxDbgNoEvents = new JCheckBox("初始化启动的activity,但是不产生任何事件");
×
90

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

96
    /**
97
     * --ignore-crashes:忽略崩溃
98
     */
99
    JCheckBox checkBoxCrashes = new JCheckBox("忽略崩溃", true);
×
100

101
    /**
102
     * --ignore-timeouts:忽略超时
103
     */
104
    JCheckBox checkBoxTimeouts = new JCheckBox("忽略超时", true);
×
105

106
    /**
107
     * --monitor-native-crashes:跟踪本地方法的崩溃问题
108
     */
109
    JCheckBox checkBoxNativeCrashes = new JCheckBox("跟踪本地方法的崩溃问题", true);
×
110

111
    /**
112
     * --ignore-security-exceptions:忽略安全异常
113
     */
114
    JCheckBox checkBoxExceptions = new JCheckBox("忽略安全异常", true);
×
115

116
    /**
117
     * --kill-process-after-error:发生错误后直接杀掉进程
118
     */
119
    JCheckBox checkBoxKill = new JCheckBox("发生错误后直接杀掉进程");
×
120

121
    /**
122
     * --wait-dbg:知道连接了调试器才执行monkey测试
123
     */
124
    JCheckBox checkBoxWaitDbg = new JCheckBox("停止Monkey执行,直到有调试器与其连接");
×
125

126
    ButtonGroup group = new ButtonGroup();
×
127

128
    /**
129
     * 缺省值
130
     */
131
    JRadioButton radioButton0 = new JRadioButton("基本信息");
×
132

133
    /**
134
     * 比较详细
135
     */
136
    JRadioButton radioButton1 = new JRadioButton("比较详细");
×
137

138
    /**
139
     * 非常详细(默认选中)
140
     */
141
    JRadioButton radioButton2 = new JRadioButton("非常详细", true);
×
142

143
    ArrayList<String> list;
144
    int flag = 0;
×
145
    String[] monkeyCmd = null;
×
146

147
    @Override
148
    public void initUI() {
149
        setPreferredSize(new Dimension(Constants.DEFAULT_PANEL_WIDTH, Constants.DEFAULT_PANEL_HEIGHT));
×
150
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
×
151

152
        JPanel devicesPanel = new JPanel();
×
153
        devicesPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
154
        initDevices(devicesPanel);
×
155
        add(devicesPanel);
×
156

157
        JPanel programPanel = new JPanel();
×
158
        programPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
159
        initProgram(programPanel);
×
160
        add(programPanel);
×
161

162
        JPanel restrainConditionPanel = new JPanel();
×
163
        restrainConditionPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
164
        initRestrainCondition(restrainConditionPanel);
×
165
        add(restrainConditionPanel);
×
166

167
        JPanel eventIntervalPanel = new JPanel();
×
168
        eventIntervalPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
169
        initEventInterval(eventIntervalPanel);
×
170
        add(eventIntervalPanel);
×
171

172
        JPanel runTimePanel = new JPanel();
×
173
        runTimePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
174
        initRunTime(runTimePanel);
×
175
        add(runTimePanel);
×
176

177
        JPanel logLevelPanel = new JPanel();
×
178
        logLevelPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
179
        initLogLevel(logLevelPanel);
×
180
        add(logLevelPanel);
×
181

182
        JPanel logPathPanel = new JPanel();
×
183
        logPathPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
184
        initLogPath(logPathPanel);
×
185
        add(logPathPanel);
×
186

187
        JPanel operationPanel = new JPanel();
×
188
        operationPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
×
189
        initOperation(operationPanel);
×
190
        add(operationPanel);
×
191
    }
×
192

193
    private void initDevices(JPanel panel) {
194
        JLabel labelDevices = new JLabel("设备列表");
×
195
        labelDevices.setPreferredSize(new Dimension(60, 25));
×
196
        comboBoxDevices.setPreferredSize(new Dimension(240, 25));
×
197
        refreshButton.setPreferredSize(new Dimension(60, 25));
×
198

199
        panel.add(labelDevices);
×
200
        panel.add(comboBoxDevices);
×
201
        panel.add(refreshButton);
×
202

203
        refreshButton.addActionListener(e -> {
×
204
            comboBoxDevices.removeAllItems();
×
205
            List<String> devices = getDevices();
×
206
            for (String device : devices) {
×
207
                comboBoxDevices.addItem(device);
×
208
            }
×
209
        });
×
210
    }
×
211

212
    private void initProgram(JPanel panel) {
213
        JLabel labelProgram = new JLabel("应用程序");
×
214
        labelProgram.setPreferredSize(new Dimension(60, 25));
×
215
        comboBoxProgram.setPreferredSize(new Dimension(240, 25));
×
216
        comboBoxProgram.setEditable(true);
×
217
        comboBoxProgram.setSelectedItem("com.shinow.*");
×
218

219
        panel.add(labelProgram);
×
220
        panel.add(comboBoxProgram);
×
221

222
        comboBoxDevices.addActionListener(e -> {
×
223
            comboBoxProgram.removeAllItems();
×
224
            comboBoxProgram.setSelectedItem("com.shinow.*");
×
225
            List<String> programs = getApplication(comboBoxDevices.getSelectedItem().toString());
×
226
            for (String program : programs) {
×
227
                comboBoxProgram.addItem(program);
×
228
            }
×
229

230
        });
×
231
    }
×
232

233
    private void initRestrainCondition(JPanel panel) {
234
        JLabel labelRestrain = new JLabel("约束条件");
×
235
        labelRestrain.setPreferredSize(new Dimension(60, 25));
×
236
        checkBoxCrashes.setPreferredSize(new Dimension(100, 25));
×
237
        checkBoxTimeouts.setPreferredSize(new Dimension(100, 25));
×
238
        checkBoxExceptions.setPreferredSize(new Dimension(110, 25));
×
239
        checkBoxNativeCrashes.setPreferredSize(new Dimension(180, 25));
×
240
        checkBoxKill.setPreferredSize(new Dimension(180, 25));
×
241
        checkBoxWaitDbg.setPreferredSize(new Dimension(280, 25));
×
242
        checkBoxHprof.setPreferredSize(new Dimension(280, 25));
×
243

244
        panel.add(labelRestrain);
×
245
        panel.add(checkBoxCrashes);
×
246
        panel.add(checkBoxTimeouts);
×
247
        panel.add(checkBoxExceptions);
×
248
        panel.add(checkBoxNativeCrashes);
×
249
        panel.add(checkBoxKill);
×
250
        panel.add(checkBoxWaitDbg);
×
251
        panel.add(checkBoxHprof);
×
252
    }
×
253

254
    private void initEventInterval(JPanel panel) {
255
        JLabel labelSpace = new JLabel("事件间隔");
×
256
        labelSpace.setPreferredSize(new Dimension(60, 25));
×
257
        textMillisecond.setPreferredSize(new Dimension(150, 25));
×
258
        textMillisecond.setDocument(new NumberPlainDocument(7));
×
259
        textMillisecond.setText("500");
×
260
        JLabel labelMillisecond = new JLabel("毫秒");
×
261
        labelMillisecond.setPreferredSize(new Dimension(40, 25));
×
262

263
        panel.add(labelSpace);
×
264
        panel.add(textMillisecond);
×
265
        panel.add(labelMillisecond);
×
266
    }
×
267

268
    private void initRunTime(JPanel panel) {
269
        JLabel labelTime = new JLabel("运行时长");
×
270
        labelTime.setPreferredSize(new Dimension(60, 25));
×
271
        textTime.setPreferredSize(new Dimension(150, 25));
×
272
        textTime.setDocument(new NumberPlainDocument(7));
×
273
        textTime.setText("1");
×
274
        comboBoxTime.setPreferredSize(new Dimension(60, 25));
×
275
        comboBoxTime.addItem(HOUR);
×
276
        comboBoxTime.addItem(MINUTE);
×
277
        comboBoxTime.addItem(SECOND);
×
278

279
        labelHour.setPreferredSize(new Dimension(50, 25));
×
280
        labelMinute.setPreferredSize(new Dimension(50, 25));
×
281
        labelSecond.setPreferredSize(new Dimension(50, 25));
×
282

283
        panel.add(labelTime);
×
284
        panel.add(textTime);
×
285
        panel.add(comboBoxTime);
×
286

287
        panel.add(labelHour);
×
288
        panel.add(labelMinute);
×
289
        panel.add(labelSecond);
×
290
    }
×
291

292
    private void initLogLevel(JPanel panel) {
293
        JLabel labelLogLevel = new JLabel("日志级别");
×
294
        labelLogLevel.setPreferredSize(new Dimension(60, 25));
×
295

296
        group.add(radioButton0);
×
297
        group.add(radioButton1);
×
298
        group.add(radioButton2);
×
299

300
        radioButton0.setPreferredSize(new Dimension(80, 25));
×
301
        radioButton1.setPreferredSize(new Dimension(80, 25));
×
302
        radioButton2.setPreferredSize(new Dimension(80, 25));
×
303

304
        panel.add(labelLogLevel);
×
305
        panel.add(radioButton0);
×
306
        panel.add(radioButton1);
×
307
        panel.add(radioButton2);
×
308
    }
×
309

310
    private void initLogPath(JPanel panel) {
311
        logPathButton.setPreferredSize(new Dimension(100, 25));
×
312
        textLogPath.setColumns(60);
×
313
        textLogPath.setEditable(false);
×
314
        textLogPath.setText("D:");
×
315

316
        panel.add(logPathButton);
×
317
        panel.add(textLogPath);
×
318

319
        logPathButton.addActionListener(e -> {
×
320
            if (e.getSource() == logPathButton) {
×
321
                JFileChooser fileChooser = new JFileChooser();
×
322
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
×
323
                int intRetVal = fileChooser.showOpenDialog(new Label());
×
324
                if (intRetVal == JFileChooser.APPROVE_OPTION) {
×
325
                    textLogPath.setText(fileChooser.getSelectedFile().getPath());
×
326
                }
327
            }
328
        });
×
329
    }
×
330

331
    private void initOperation(JPanel panel) {
332
        executeButton.setPreferredSize(new Dimension(100, 25));
×
333
        resetButton.setPreferredSize(new Dimension(100, 25));
×
334
        interruptButton.setPreferredSize(new Dimension(100, 25));
×
335

336
        panel.add(executeButton);
×
337
        panel.add(resetButton);
×
338
        panel.add(interruptButton);
×
339

340
        interruptButton.setEnabled(false);
×
341

342
        executeButton.addActionListener(e -> execute());
×
343

344
        resetButton.addActionListener(e -> reset());
×
345

346
        interruptButton.addActionListener(e -> interrupt());
×
347

348
    }
×
349

350
    private void execute() {
351
        String combinedOptionCmd = getCombinedOptionCmd();
×
352

353
        boolean isOk = checkCondition();
×
354
        if (!isOk) {
×
355
            return;
×
356
        }
357

358
        String logLevel = queryLogLevelString();
×
359
        String logFile = textLogPath.getText() + "\\" + LOG_NAME + DateUtils.getCurrentDateString() + ".txt";
×
360

361
        monkeyCmd = new String[] { CMD, "/C",
×
362
                "adb -s " + comboBoxDevices.getSelectedItem() + " shell monkey -p "
×
363
                        + comboBoxProgram.getSelectedItem() + combinedOptionCmd + " --throttle "
×
364
                        + textMillisecond.getText() + "" + logLevel + "" + TRANSACTIONCOUNT + " > " + logFile };
×
365

366
        logger.info("Monkey: {}", monkeyCmd[2]);
×
367

368
        flag = 0;
×
369

370
        try {
371
            monkeyProcess = Runtime.getRuntime().exec(monkeyCmd);
×
372
        } catch (Exception ex) {
×
373
            logger.error("Exception", ex);
×
374
        }
×
375

376
        executeButton.setEnabled(false);
×
377
        resetButton.setEnabled(false);
×
378
        interruptButton.setEnabled(true);
×
379

380
        // 倒计时文本
381
        labelHour.setVisible(true);
×
382
        labelMinute.setVisible(true);
×
383
        labelSecond.setVisible(true);
×
384

385
        // 获取时间类型
386
        String timeType = (String) comboBoxTime.getSelectedItem();
×
387
        long time = Long.parseLong(textTime.getText());
×
388
        if (Objects.equals(timeType, HOUR)) {
×
389
            time *= 3600;
×
390
        } else if (Objects.equals(timeType, MINUTE)) {
×
391
            time *= 60;
×
392
        }
393
        threadTimeType = new Thread(new CountdownRunnable(time));
×
394
        threadTimeType.start();
×
395
    }
×
396

397
    private void reset() {
398
        // 重置约束条件
399
        checkBoxCrashes.setSelected(true);
×
400
        checkBoxTimeouts.setSelected(true);
×
401
        checkBoxExceptions.setSelected(true);
×
402
        checkBoxNativeCrashes.setSelected(true);
×
403
        // 重置日志级别
404
        radioButton0.setSelected(false);
×
405
        radioButton1.setSelected(false);
×
406
        radioButton2.setSelected(true);
×
407
        // 重置事件间隔
408
        textMillisecond.setText("500");
×
409
        // 重置运行时长
410
        textTime.setText("1");
×
411
    }
×
412

413
    private void interrupt() {
414
        // 杀掉Monkey执行进程
415
        interruptThread();
×
416
        executeButton.setEnabled(true);
×
417
        resetButton.setEnabled(true);
×
418
        interruptButton.setEnabled(false);
×
419
    }
×
420

421
    private String getCombinedOptionCmd() {
422
        String ignoreCrashes = checkBoxCrashes.isSelected() ? " --ignore-crashes" : "";
×
423
        String ignoreTimeouts = checkBoxTimeouts.isSelected() ? " --ignore-timeouts" : "";
×
424
        String monitorNativeCrashes = checkBoxNativeCrashes.isSelected() ? " --monitor-native-crashes" : "";
×
425
        String ignoreSecurityExceptions = checkBoxExceptions.isSelected() ? " --ignore-security-exceptions" : "";
×
426
        String hprof = checkBoxHprof.isSelected() ? " --hprof" : "";
×
427
        String killProcessAfterError = checkBoxKill.isSelected() ? " --kill-process-after-error" : "";
×
428
        String waitDbg = checkBoxWaitDbg.isSelected() ? " --wait-dbg" : "";
×
429
        String dbgNoEvents = checkBoxDbgNoEvents.isSelected() ? "--dbg-no-events" : "";
×
430
        return ignoreCrashes + ignoreTimeouts + ignoreSecurityExceptions + monitorNativeCrashes + hprof
×
431
                + killProcessAfterError + waitDbg + dbgNoEvents;
432
    }
433

434
    private boolean checkCondition() {
435
        // 判断设备列表和应用程序是否为空
436
        if (comboBoxDevices.getItemCount() == 0) {
×
437
            new MyDialog(MSG4).setVisible(true);
×
438
            refreshButton.requestFocus();
×
439
            return false;
×
440
        }
441
        if (comboBoxProgram.getItemCount() == 0) {
×
442
            new MyDialog(MSG5).setVisible(true);
×
443
            return false;
×
444
        }
445
        // 判断事件间隔和运行时长是否为空
446
        if (textMillisecond.getText().length() == 0) {
×
447
            new MyDialog(MSG2).setVisible(true);
×
448
            textMillisecond.requestFocus();
×
449
            return false;
×
450
        }
451
        if (textTime.getText().length() == 0) {
×
452
            new MyDialog(MSG2).setVisible(true);
×
453
            textTime.requestFocus();
×
454
            return false;
×
455
        }
456
        if (textLogPath.getText().length() == 0) {
×
457
            new MyDialog(MSG6).setVisible(true);
×
458
            logPathButton.requestFocus();
×
459
            return false;
×
460
        }
461
        return true;
×
462
    }
463

464
    private String queryLogLevelString() {
465
        if (radioButton0.isSelected()) {
×
466
            return " -v ";
×
467
        } else if (radioButton1.isSelected()) {
×
468
            return " -v -v ";
×
469
        } else if (radioButton2.isSelected()) {
×
470
            return " -v -v -v ";
×
471
        }
472
        return "";
×
473
    }
474

475
    /**
476
     * 中断Monkey命令
477
     */
478
    public void interruptThread() {
479

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

482
        String[] cmd1 = new String[] { CMD, "/c", CMD_PS_A + comboBoxDevices.getSelectedItem() + CMD_PS_B };
×
483
        executeCommand(cmd1, MONKEY);
×
484

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

488
        String[] cmd2 = null;
×
489
        String pid = "";
×
490
        for (String s : listPid) {
×
491
            pid = s;
×
492
            cmd2 = new String[]{CMD, "/c", CMD_KILL_A + comboBoxDevices.getSelectedItem() + CMD_KILL_B + pid};
×
493
            executeCommand(cmd2, MONKEY);
×
494
        }
×
495

496
        flag = 1;
×
497

498
        monkeyProcess.destroy();
×
499

500
        labelHour.setVisible(false);
×
501
        labelMinute.setVisible(false);
×
502
        labelSecond.setVisible(false);
×
503

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

506
    }
×
507

508
    private List<String> getDevices() {
509
        List<String> devices = new ArrayList<>();
×
510
        logger.info("get device list start");
×
511
        Process process = null;
×
512
        try {
513
            process = Runtime.getRuntime().exec("adb devices");
×
514
        } catch (IOException e) {
×
515
            logger.error("exec command failed: " + e.getMessage());
×
516
        }
×
517
        if (process == null) {
×
518
            logger.error("process is null");
×
519
            return devices;
×
520
        }
521
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
×
522
            String line;
523
            while ((line = reader.readLine()) != null) {
×
524
                if (line.contains("device") && !line.contains("List of")) {
×
525
                    line = line.substring(0, line.length() - 7);
×
526
                    logger.info("device name: " + line);
×
527
                    devices.add(line);
×
528
                }
529
            }
530
        } catch (IOException e) {
×
531
            logger.error("read failed: " + e.getMessage());
×
532
        } finally {
533
            IOUtils.closeQuietly(process.getOutputStream());
×
534
            IOUtils.closeQuietly(process.getErrorStream());
×
535
            IOUtils.closeQuietly(process.getInputStream());
×
536
        }
537
        logger.info("get device list end");
×
538
        return devices;
×
539
    }
540

541
    private List<String> getApplication(String device) {
542
        List<String> apps = new ArrayList<>();
×
543
        logger.info("get application list start");
×
544
        Process process = null;
×
545
        try {
546
            process = Runtime.getRuntime().exec(new String[]{"adb", "-s", device, "shell", "pm", "list", "packages"});
×
547
        } catch (IOException e) {
×
548
            logger.error("exec command failed: " + e.getMessage());
×
549
        }
×
550
        if (process == null) {
×
551
            logger.error("process is null");
×
552
            return apps;
×
553
        }
554
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
×
555
            String line;
556
            while ((line = reader.readLine()) != null) {
×
557
                if (line.contains("package:")) {
×
558
                    logger.info("application name:" + line);
×
559
                    apps.add(line.replace("package:", ""));
×
560
                }
561
            }
562
        } catch (IOException e) {
×
563
            logger.error("read failed: " + e.getMessage());
×
564
        } finally {
565
            IOUtils.closeQuietly(process.getOutputStream());
×
566
            IOUtils.closeQuietly(process.getErrorStream());
×
567
            IOUtils.closeQuietly(process.getInputStream());
×
568
        }
569
        logger.info("get application list end");
×
570
        return apps;
×
571
    }
572

573
    private void executeCommand(String[] cmd, String keyValue) {
574
        logger.info("exec cmd start");
×
575
        list = new ArrayList<>();
×
576
        Process process = null;
×
577
        try {
578
            process = Runtime.getRuntime().exec(cmd);
×
579
        } catch (IOException e) {
×
580
            logger.error("exec command failed: " + e.getMessage());
×
581
        }
×
582
        if (process == null) {
×
583
            logger.error("process is null");
×
584
            return;
×
585
        }
586
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
×
587
            String line;
588
            while ((line = reader.readLine()) != null) {
×
589
                if (line.contains(keyValue)) {
×
590
                    line = line.replace(" ", ":");
×
591
                    System.out.println("[" + keyValue + "][" + line + "]");
×
592
                    String[] str = line.split(":");
×
593
                    System.out.println(str.length);
×
594
                    for (int i = 1; i < str.length; i++) {
×
595
                        if (str[i].length() > 0) {
×
596
                            logger.info("Pid: " + str[i]);
×
597
                            list.add(str[i]);
×
598
                            break;
×
599
                        }
600
                    }
601
                }
×
602
            }
603
        } catch (IOException e) {
×
604
            logger.error("read failed: " + e.getMessage());
×
605
        } finally {
606
            IOUtils.closeQuietly(process.getOutputStream());
×
607
            IOUtils.closeQuietly(process.getErrorStream());
×
608
            IOUtils.closeQuietly(process.getInputStream());
×
609
        }
610
        logger.info("exec cmd end");
×
611
    }
×
612

613
    /**
614
     * 倒计时
615
     * 
616
     */
617
    class CountdownRunnable implements Runnable {
618
        private long times;
619

620
        public CountdownRunnable(long times) {
×
621
            this.times = times;
×
622
        }
×
623

624
        @Override
625
        public void run() {
626
            // 自定义倒计时时间
627
            long time = times;
×
628
            long hour = 0;
×
629
            long minute = 0;
×
630
            long seconds = 0;
×
631

632
            if (time >= 0) {
×
633
                for (int i = 0; i <= time; i++) {
×
634
                    // 监控Monkey命令
635
                    monitorMonkey(time, MONKEY);
×
636
                    // 监控Monkey命令操作的App
637
                    monitorApp(time, comboBoxProgram.getSelectedItem().toString());
×
638
                    // 判断标识,是否中断操作
639
                    System.out.println("flag==1?Interrupt:Continue:" + flag);
×
640
                    if (flag == 1) {
×
641
                        break;
×
642
                    }
643
                    hour = time / 3600;
×
644
                    minute = (time - hour * 3600) / 60;
×
645
                    seconds = time - hour * 3600 - minute * 60;
×
646
                    labelHour.setText(hour + HOUR);
×
647
                    labelMinute.setText(minute + MINUTE);
×
648
                    labelSecond.setText(seconds + SECOND);
×
649
                    try {
650
                        Thread.sleep(1000);
×
651
                    } catch (InterruptedException e) {
×
652
                        logger.error("InterruptedException {}", e.getMessage());
×
653
                        Thread.currentThread().interrupt();
×
654
                    }
×
655
                    // 正常结束
656
                    if (time == 0) {
×
657
                        Thread.currentThread().interrupt();
×
658
                        interruptThread();
×
659
                        executeButton.setEnabled(true);
×
660
                        resetButton.setEnabled(true);
×
661
                        interruptButton.setEnabled(false);
×
662
                    }
663
                    i--;
×
664
                    time--;
×
665
                }
666
                if (flag == 1) {
×
667
                    Thread.currentThread().interrupt();
×
668
                    threadTimeType.interrupt();
×
669
                    executeButton.setEnabled(true);
×
670
                    resetButton.setEnabled(true);
×
671
                    interruptButton.setEnabled(false);
×
672
                }
673
            }
674
        }
×
675

676
        /**
677
         * 间隔60秒监控一次运行monkey命令是否为运行状态,或已关闭
678
         * 
679
         * @param time     当前剩余执行时间
680
         * @param keyValue Monkey命令的进程名称
681
         */
682
        private void monitorMonkey(long time, String keyValue) {
683
            if ((time - 1) % 120 == 0) {
×
684
                logger.info("监控[" + keyValue + "]线程是否执行完毕---开始");
×
685
                logger.info("每60秒监听一次,此时time的值:" + (time - 1));
×
686
                String[] cmd = new String[] { CMD, "/c",
×
687
                        CMD_PS_A + comboBoxDevices.getSelectedItem() + CMD_PS_B };
×
688
                logger.info("当前命令:" + cmd[2]);
×
689
                executeCommand(cmd, keyValue);
×
690
                logger.info("当前线程数:" + list.size());
×
691
                if (list.size() == 0) {
×
692
                    String log = textLogPath.getText();
×
693
                    System.out.println(textLogPath.getText());
×
694
                    String getDate = DateUtils.getCurrentDateString();
×
695
                    // 日志文件路径
696
                    String logFile = log.substring(0, log.indexOf("java_monkey_log")) + LOG_NAME + getDate + ".txt";
×
697
                    textLogPath.setText(logFile);
×
698
                    System.out.println("monkeyCmd[2];" + monkeyCmd[2]);
×
699
                    monkeyCmd[2] = monkeyCmd[2].substring(0, monkeyCmd[2].indexOf("java_monkey_log"))
×
700
                            + "java_monkey_log" + getDate + ".txt";
701
                    logger.info("Monkey命令已经停止,再次执行");
×
702
                    logger.info("monkeyCmd[2];" + monkeyCmd[2]);
×
703
                    String[] monkeyCommand = new String[] { CMD, "/c", monkeyCmd[2] };
×
704
                    logger.info("执行");
×
705
                    // 再次执行
706
                    try {
707
                        monkeyProcess = Runtime.getRuntime().exec(monkeyCommand);
×
708
                    } catch (Exception e) {
×
709
                        logger.error("Exception", e);
×
710
                    }
×
711
                }
712
                logger.info("监控[" + keyValue + "]线程是否执行完毕---结束");
×
713
            }
714
        }
×
715

716
        /**
717
         * 间隔60秒监控一次运行app是否是启动状态,或崩溃掉
718
         * 
719
         * @param time     当前剩余执行时间
720
         * @param keyValue App的进程名称
721
         */
722
        private void monitorApp(long time, String keyValue) {
723
            if ((time - 1) % 120 == 0) {
×
724
                logger.info("监控[" + keyValue + "]线程是否执行完毕---开始");
×
725
                logger.info("每60秒监听一次,此时time的值:" + (time - 1));
×
726
                String[] cmd = new String[] { CMD, "/c",
×
727
                        CMD_PS_A + comboBoxDevices.getSelectedItem() + CMD_PS_B };
×
728
                logger.info("当前命令:" + cmd[2]);
×
729
                executeCommand(cmd, keyValue);
×
730
                logger.info("当前线程数:" + list.size());
×
731
                if (list.size() == 0) {
×
732
                    logger.info("[" + keyValue + "]已经关闭或崩溃,无法继续执行Monkey,退出系统");
×
733
                    logger.info("监控[" + keyValue + "]线程是否执行完毕---结束");
×
734
                    // 杀掉Monkey执行进程
735
                    interruptThread();
×
736
                    // System.gc();
737
                }
738
                logger.info("监控[" + keyValue + "]线程是否执行完毕---结束");
×
739
            }
740
        }
×
741
    }
742

743
    static class MyDialog extends JDialog {
744

745
        @Serial
746
        private static final long serialVersionUID = 1L;
747

748
        MyDialog(String msg3) {
749
            super((Frame)null, "提示", true);
×
750
            setSize(320, 180);
×
751
            Container container = getContentPane();
×
752
            container.setLayout(null);
×
753
            JLabel jl = new JLabel(msg3);
×
754
            jl.setBounds(70, 1, 200, 100);
×
755
            JButton jbb = new JButton("确    定");
×
756
            jbb.setBounds(97, 80, 100, 25);
×
757
            container.add(jl);
×
758
            container.add(jbb);
×
759

760
            // 设置位置
761
            int w = (Toolkit.getDefaultToolkit().getScreenSize().width - 320) / 2;
×
762
            int h = (Toolkit.getDefaultToolkit().getScreenSize().height - 180) / 2;
×
763

764
            setLocation(w, h);
×
765

766
            jbb.addActionListener(e -> dispose());
×
NEW
767
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
×
768
        }
×
769
    }
770
}
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