• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

jiangxincode / ApkToolBoxGUI / #621

29 Feb 2024 03:35PM UTC coverage: 3.233% (+0.004%) from 3.229%
#621

push

jiangxincode
optimize the monkey test panel

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

18 existing lines in 1 file now uncovered.

240 of 7424 relevant lines covered (3.23%)

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_PS_A = "adb -s ";
34
    private static final String CMD_PS_B = " shell ps";
35
    private static final String CMD_KILL_A = "adb -s ";
36
    private static final String CMD_KILL_B = " shell kill ";
37

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

40
    private static final String TRANSACTIONCOUNT = "9999";
41

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

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

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

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

62
    Thread threadTimeType = null;
×
63
    Process monkeyProcess = null;
×
64

NEW
65
    JComboBox<String> comboBoxDevices = new JComboBox<>();
×
66
    JButton refreshButton = new JButton("刷新");
×
67

68
    JButton logPathButton = new JButton("选择路径");
×
NEW
69
    JButton executeButton = new JButton("运行命令");
×
70

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

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

NEW
81
    JComboBox<String> comboBoxProgram = new JComboBox<>();
×
NEW
82
    JComboBox<String> comboBoxTime = new JComboBox<>();
×
83

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

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

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

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

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

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

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

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

124
    ButtonGroup group = new ButtonGroup();
×
125

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

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

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

141
    String logLevel = "";
×
142
    ArrayList<String> list;
143
    int flag = 0;
×
144
    String[] monkeyCmd = null;
×
145

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

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

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

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

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

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

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

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

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

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

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

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

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

NEW
218
        panel.add(labelProgram);
×
NEW
219
        panel.add(comboBoxProgram);
×
220

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

UNCOV
229
        });
×
NEW
230
    }
×
231

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

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

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

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

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

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

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

NEW
286
        panel.add(labelHour);
×
NEW
287
        panel.add(labelMinute);
×
NEW
288
        panel.add(labelSecond);
×
UNCOV
289
    }
×
290

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

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

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

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

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

NEW
315
        panel.add(logPathButton);
×
NEW
316
        panel.add(textLogPath);
×
317

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

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

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

339
        interruptButton.setEnabled(false);
×
340

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

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

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

347
    }
×
348

349
    private void execute() {
NEW
350
        String ignoreCrashes = checkBoxCrashes.isSelected() ? " --ignore-crashes" : "";
×
NEW
351
        String ignoreTimeouts = checkBoxTimeouts.isSelected() ? " --ignore-timeouts" : "";
×
NEW
352
        String monitorNativeCrashes = checkBoxNativeCrashes.isSelected() ? " --monitor-native-crashes" : "";
×
NEW
353
        String ignoreSecurityExceptions = checkBoxExceptions.isSelected() ? " --ignore-security-exceptions" : "";
×
NEW
354
        String hprof = checkBoxHprof.isSelected() ? " --hprof" : "";
×
NEW
355
        String killProcessAfterError = checkBoxKill.isSelected() ? " --kill-process-after-error" : "";
×
NEW
356
        String waitDbg = checkBoxWaitDbg.isSelected() ? " --wait-dbg" : "";
×
NEW
357
        String dbgNoEvents = checkBoxDbgNoEvents.isSelected() ? "--dbg-no-events" : "";
×
358

NEW
359
        boolean isOk = checkCondition();
×
NEW
360
        if (!isOk) {
×
NEW
361
            return;
×
362
        }
363

NEW
364
        logLevel = queryLogLevelString();
×
NEW
365
        String logFile = textLogPath.getText() + "\\" + LOG_NAME + DateUtils.getCurrentDateString() + ".txt";
×
366

NEW
367
        monkeyCmd = new String[] { "cmd.exe", "/C",
×
NEW
368
                "adb -s " + comboBoxDevices.getSelectedItem() + " shell monkey -p "
×
NEW
369
                        + comboBoxProgram.getSelectedItem() + "" + ignoreCrashes + "" + ignoreTimeouts + ""
×
370
                        + ignoreSecurityExceptions + "" + monitorNativeCrashes + " --throttle "
NEW
371
                        + textMillisecond.getText() + "" + logLevel + "" + TRANSACTIONCOUNT + " > " + logFile };
×
372

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

NEW
375
        flag = 0;
×
376

377
        try {
NEW
378
            monkeyProcess = Runtime.getRuntime().exec(monkeyCmd);
×
NEW
379
        } catch (Exception ex) {
×
NEW
380
            logger.error("Exception", ex);
×
NEW
381
        }
×
382

NEW
383
        executeButton.setEnabled(false);
×
NEW
384
        resetButton.setEnabled(false);
×
NEW
385
        interruptButton.setEnabled(true);
×
386

387
        // 倒计时文本
NEW
388
        labelHour.setVisible(true);
×
NEW
389
        labelMinute.setVisible(true);
×
NEW
390
        labelSecond.setVisible(true);
×
391

392
        // 获取时间类型
NEW
393
        String timeType = (String) comboBoxTime.getSelectedItem();
×
NEW
394
        long time = Long.parseLong(textTime.getText());
×
NEW
395
        if (Objects.equals(timeType, HOUR)) {
×
NEW
396
            time *= 3600;
×
NEW
397
        } else if (Objects.equals(timeType, MINUTE)) {
×
NEW
398
            time *= 60;
×
399
        }
NEW
400
        threadTimeType = new Thread(new CountdownRunnable(time));
×
NEW
401
        threadTimeType.start();
×
NEW
402
    }
×
403

404
    private void reset() {
405
        // 重置约束条件
NEW
406
        checkBoxCrashes.setSelected(true);
×
NEW
407
        checkBoxTimeouts.setSelected(true);
×
NEW
408
        checkBoxExceptions.setSelected(true);
×
NEW
409
        checkBoxNativeCrashes.setSelected(true);
×
410
        // 重置日志级别
NEW
411
        radioButton0.setSelected(false);
×
NEW
412
        radioButton1.setSelected(false);
×
NEW
413
        radioButton2.setSelected(true);
×
414
        // 重置事件间隔
NEW
415
        textMillisecond.setText("500");
×
416
        // 重置运行时长
NEW
417
        textTime.setText("1");
×
NEW
418
    }
×
419

420
    private void interrupt() {
421
        // 杀掉Monkey执行进程
NEW
422
        interruptThread();
×
NEW
423
        executeButton.setEnabled(true);
×
NEW
424
        resetButton.setEnabled(true);
×
NEW
425
        interruptButton.setEnabled(false);
×
NEW
426
    }
×
427

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

458
    private String queryLogLevelString() {
NEW
459
        if (radioButton0.isSelected()) {
×
NEW
460
            return " -v ";
×
NEW
461
        } else if (radioButton1.isSelected()) {
×
NEW
462
            return " -v -v ";
×
NEW
463
        } else if (radioButton2.isSelected()) {
×
NEW
464
            return " -v -v -v ";
×
465
        }
NEW
466
        return "";
×
467
    }
468

469
    /**
470
     * 中断Monkey命令
471
     */
472
    public void interruptThread() {
473

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

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

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

482
        String[] cmd2 = null;
×
483
        String pid = "";
×
NEW
484
        for (String s : listPid) {
×
NEW
485
            pid = s;
×
NEW
486
            cmd2 = new String[]{"cmd.exe", "/c", CMD_KILL_A + comboBoxDevices.getSelectedItem() + CMD_KILL_B + pid};
×
UNCOV
487
            executeCommand(cmd2, MONKEY);
×
UNCOV
488
        }
×
489

490
        flag = 1;
×
491

492
        monkeyProcess.destroy();
×
493

494
        labelHour.setVisible(false);
×
495
        labelMinute.setVisible(false);
×
496
        labelSecond.setVisible(false);
×
497

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

500
    }
×
501

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

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

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

607
    /**
608
     * 倒计时
609
     * 
610
     */
611
    class CountdownRunnable implements Runnable {
612
        private long times;
613

614
        public CountdownRunnable(long times) {
×
615
            this.times = times;
×
616
        }
×
617

618
        @Override
619
        public void run() {
620
            // 自定义倒计时时间
NEW
621
            long time = times;
×
622
            long hour = 0;
×
623
            long minute = 0;
×
624
            long seconds = 0;
×
625

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

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

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

737
    static class MyDialog extends JDialog {
738

739
        @Serial
740
        private static final long serialVersionUID = 1L;
741

742
        MyDialog(String msg3) {
NEW
743
            super((Frame)null, "提示", true);
×
NEW
744
            setSize(320, 180);
×
NEW
745
            Container container = getContentPane();
×
UNCOV
746
            container.setLayout(null);
×
UNCOV
747
            JLabel jl = new JLabel(msg3);
×
748
            jl.setBounds(70, 1, 200, 100);
×
749
            JButton jbb = new JButton("确    定");
×
750
            jbb.setBounds(97, 80, 100, 25);
×
751
            container.add(jl);
×
752
            container.add(jbb);
×
753

754
            // 设置位置
755
            int w = (Toolkit.getDefaultToolkit().getScreenSize().width - 320) / 2;
×
756
            int h = (Toolkit.getDefaultToolkit().getScreenSize().height - 180) / 2;
×
757

NEW
758
            setLocation(w, h);
×
759

NEW
760
            jbb.addActionListener(e -> dispose());
×
NEW
761
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
×
UNCOV
762
        }
×
763
    }
764
}
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