adb打开安卓设置界面

1
adb shell am start -n com.android.settings/.Settings

如果不能打开,则可能是手机厂商重写了设置界面。

打开华为手机设置界面,打开EMUI设置界面

例如我的华为手机(EMUI9.0)的设置界面的activity是:com.android.settings/.HWSettings

1
adb shell am start -n com.android.settings/.HWSettings

OPPO手机打开设置界面

1
adb shell am start -n com.android.settings/com.oppo.settings.SettingsActivity

步骤

  1. 先设置DO_NOTHING_ON_CLOSE:frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
  2. 然后再调用frame.addWindowListener方法,重写windowClosing方法,在windowClosing方法里面弹出确认对话框。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import javax.swing.*;  
import java.awt.event.*;

public class CloseConfirmation {

public static void main(String[] args) {
JFrame frame = new JFrame("Close Confirmation Example");
frame.setSize(300, 200);


frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
int confirm = JOptionPane.showConfirmDialog(frame, "Are you sure you want to close?");
if (confirm == JOptionPane.YES_OPTION) {
frame.dispose();
}
}
});
frame.setVisible(true);
}
}

示例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private void frameSettings() {
// 取消默认关闭操作
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
// 自己实现windowClosing
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// int result = JOptionPane.showConfirmDialog(contentPane, "确认关闭");
int result = JOptionPane.showConfirmDialog(contentPane, "确定关闭", "是否关闭窗体", JOptionPane.YES_NO_OPTION);


switch (result) {
case JOptionPane.OK_OPTION:
super.windowClosing(e);
// adbJPanels.getStopBtn().doClick();
universalPanels.getBtnStop().doClick();
scrcpyJPanels.getBtnKillScrcpy().doClick();
System.out.println("窗体正在关闭。。。。。。。。。。。。");
// ThreadSleep.seconds(5);
System.exit(0);
break;
// default:
// frame.pack();
// break;
}
}
});
// 永远置顶
frame.setAlwaysOnTop(true);
// 调整窗体到最佳大小
frame.pack();
// 显示窗体
frame.setVisible(true);
}

前言

需求

使用adb命令点击屏幕上的某个按钮

adb在屏幕的指定坐标上点击

如果我们知道按钮的坐标[x,y]的话,使用adb shell input tap x y命令可Android设备屏幕上的x,y坐标上点击。

如何获取要点击的按钮的坐标

答案就是使用adb shell uiautomator dump先分析当前activity的UI,然后在命令生成的xml文件中找到要点击的按钮的坐标x,y。

有了坐标之后,再使用adb shell input tap x y进行点击即可。

示例

adb shell uiautomator dump

1
adb shell uiautomator dump

命令会在Android设备上生成一个xml文件:

1
2
3
4
G:\dev2\idea_workspace\MyJavaTools\runable>adb shell uiautomator dump
UI hierchary dumped to: /sdcard/window_dump.xml

G:\dev2\idea_workspace\MyJavaTools\runable>

从Android上复制xml文件到电脑上

使用adb pull命令从Android中复制文件到电脑上:

1
adb pull /sdcard/window_dump.xml D:\Desktop\test\获取activity按钮位置

复制成功效果:

1
2
3
4
G:\dev2\idea_workspace\MyJavaTools\runable>adb pull /sdcard/window_dump.xml D:\Desktop\test\获取activity按钮位置
/sdcard/window_dump.xml: 1 file pulled...pped. 2.2 MB/s (22056 bytes in 0.010s)

G:\dev2\idea_workspace\MyJavaTools\runable>

分析xml文件

在电脑上用vscode打开这个xml文件。按Ctrl+F,打开查找,在搜索框中输入要点击的按钮的文字。一般这个时候就能找到这个按钮对应的标签。

获取按钮的bounds属性

查找文字为”反馈”的按钮:

1
2
3
4
5
6
7
8
<node index="0" text="" resource-id="com.byted.pangle:id/tt_top_area" class="android.widget.LinearLayout" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,144]">
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][936,144]">
<node index="0" text="反馈" resource-id="com.byted.pangle:id/tt_top_dislike" class="android.widget.TextView" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[720,60][888,144]" /></node>
<node NAF="true" index="1" text="" resource-id="com.byted.pangle:id/tt_reward_full_count_down" class="android.widget.LinearLayout" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[936,60][1032,144]">
<node NAF="true" index="0" text="" resource-id="com.byted.pangle:id/tt_reward_full_count_down_after" class="android.widget.LinearLayout" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[966,84][1002,120]">
<node index="0" text="" resource-id="com.byted.pangle:id/tt_reward_full_count_down_after_close" class="android.widget.ImageView" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[966,84][1002,120]" /></node>
</node>
</node>

这条标签的内容如下:

1
<node index="0" text="反馈" resource-id="com.byted.pangle:id/tt_top_dislike" class="android.widget.TextView" package="com.xk.qreader" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[720,60][888,144]" /></node>

标签中的信息很多,我们需要的信息在这条标签的末尾bounds属性:bounds="[720,60][888,144]"

这表示”反馈”按钮占据的矩形的左上角的坐标为:[720,60],右下角的坐标为[888,144];

计算中点的坐标

有了两个坐标点之后,我们计算出中点的坐标。得到x=888.0, y=144.0

adb命令点击按钮的中点坐标

得到按钮的中点坐标之后,就可以使用adb命令进行点击了:

1
adb shell input tap 804.0 102.0

参考资料

https://blog.csdn.net/growing_tree/article/details/110606365

文心一言 回答

问:

adb如何获取顶部activity中的按钮的位置

答:
要在Android Debug Bridge (ADB)中获取顶部Activity中的按钮位置,你需要使用ADB的命令行工具并结合Android设备的屏幕坐标系统。以下是获取顶部Activity中按钮位置的一般步骤:

  1. 确保你的Android设备已连接到计算机,并已启用开发者选项和USB调试模式。在设备上打开开发者选项,然后启用USB调试模式。
  2. 打开终端或命令提示符,导航到ADB的安装目录。
  3. 运行以下命令来查看当前连接的Android设备列表:
    1
    adb devices
    确保你的设备显示在列表中。
  4. 获取顶部Activity的焦点。你可以使用以下命令将焦点切换到顶部Activity:
    1
    adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp'
    这将显示当前具有焦点的Activity的相关信息。
  5. 找到你想要获取位置的按钮的视图ID。你可以使用以下命令来获取当前Activity的布局层次结构:
    1
    adb shell uiautomator dump
    这将生成一个XML文件,其中包含当前Activity的布局层次结构信息。你可以在计算机上找到这个XML文件,通常位于/sdcard/window_dump.xml
  6. 在XML文件中找到你想要获取位置的按钮的视图ID。你可以使用文本编辑器或XML解析器来打开XML文件,并查找包含按钮的视图ID。通常,视图ID的格式为@id/button_id
  7. 使用以下命令来获取按钮的位置:
    1
    adb shell uiautomator dump | grep -E 'viewId=.*button_id'
    button_id替换为你在步骤6中找到的按钮视图ID。这将显示包含按钮位置的相关信息。
  8. 从输出结果中提取按钮的位置信息。你可以查找包含boundslocation的行,这些行将提供按钮的位置坐标。通常,你会看到类似以下的输出:
    1
    viewId=com.example.app:id/button_id bounds=[0, 0][100, 50]
    这表示按钮的左上角坐标为(0, 0),右下角坐标为(100, 50)。你可以根据需要提取这些坐标值。
    请注意,这些步骤假设你已经连接到Android设备并具有适当的权限来执行ADB命令。此外,由于Android设备和应用程序的布局可能有所不同,因此你可能需要根据实际情况进行适当的调整。

自动关闭JOptionPane弹窗

JOptionPane定时关闭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package adbs.main.ui.jpanels.auto;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.Timer;

public class AutoCloseJOption {

private static final int TIME_VISIBLE = 3000;

public static void main(String[] args) {

final JFrame frame1 = new JFrame("My App");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setSize(100, 100);
frame1.setLocation(100, 100);

JButton button = new JButton("My Button");
frame1.getContentPane().add(button);

button.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
JOptionPane pane = new JOptionPane("Message", JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = pane.createDialog(null, "Title");
dialog.setModal(false);
dialog.setVisible(true);

new Timer(TIME_VISIBLE, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
}).start();
}
});

frame1.setVisible(true);

}
}

参考资料

https://www.w3cschool.cn/java/codedemo-484052162.html
https://cloud.tencent.com/developer/ask/sof/102428944

问题描述

问题描述,前几天我手贱,使用鲁大师清理垃圾的时候,它说我的主板驱动应该更新。结果我更新之后,新加的内存条识别不出来了。

台式机买的二手的,内存条是4GB DDR3 13333MHz的,后面我买了一个新的内存条8GB 1600Mhz的

现在这根新的内存条无法识别。

恢复记录

调整内存条位置

把8g的内存条和4g的调换,4g的放到1号插槽(靠近CPU的插槽),8g的放到插槽2。

BIOS设置

进入BIOS

重启电脑,然后狂按del键,进入BIOS。
BIOS主界面如下图所示:
BIOS主界面

让电脑识别到8G内存条:调整8G内存条的频率和时序

在BIOS里面按箭头按钮,选择 Over Cloci/Voltage按enter键进入:
Over Cloci/Voltage

把8g的内存条的频率调低,调成4G的一样的1333MHz:DRAM Frequency选择1333MHz
把时序调成手动的:Configure DRAM Timing By SPD 选择Manual。

这样两个内存条的频率都一样了,电脑应该就能识别到了。

在BIOS查看内存信息

回到BIOS主界面,进入Standard BOIS Feature。然后选择第二项System Infomation,按enter键,

System Information

可以看到内存大小时12G,8G内存条识别到了。

限定4G内存条的大小

回到BIOS主界面,进入Advanced Chipset Feature,然后Memory Remap Feature选择Enable。如下图所示:

然后按F10保存并退出。

重启之后

重启之后,打开任务管理器,查看里面的性能选项卡,可以看到此时电脑有12G的内存。

但是比较奇怪,有1G的内存是为硬件保留的。

限定内存条1的大小为3G

最后效果:
为硬件保存的内存为1G

接下来按win+R键,打开运行,输入msconfig,然后选择正常启动。

msconfig选择 正常启动:

系统配置选正常启动

硬件保留的内存从1G减少到8.8M

正常启动之后为硬件保留的内存减少了:

为硬件保留的内存为8.8MN

至于,为什么减少了,我不知道。

反正大值思路就是这样,之前我设置好了一次。好像是更新主板驱动之后,又不行了。

这次调整好了,就记录一下。万一下次再有这样的故障,我好再次调整。

问题描述

最近我的荣耀v10用USB连到电脑上,电脑无法识别。连到另一台电脑上却可以识别。

在无法识别的电脑上,我打开设备管理器compmgmt.msc查看,发现HDB interface有感叹号。

这是因为没有华为的手机驱动造成的,我之前的手机是可以连接到这台电脑上的,为什么现在又连不上了呢。

原来是因为我嫌电脑上的华为手机助手太碍眼,把它卸掉了。

如何安装华为的手机驱动

下载,安装 华为手机助手到电脑上。即可。

获取系统版本

1
adb shell getprop ro.build.version.release

获取系统api版本

1
adb shell getprop ro.build.version.sdk

获取手机系统版本

1
adb shell getprop ro.build.version.release

获取手机设备型号

1
adb shell getprop ro.product.model

获取手机厂商名称

1
adb shell getprop ro.product.brand

获取手机序列号

1
adb get-serialno
1
adb shell getprop ro.serialno

参考资料

https://blog.csdn.net/l_vaule/article/details/79866396

adb命令收集

获取内部版本号

1
adb shell getprop ro.build.display.innerver

获取按键值

1
adb shell getevent

获取apk信息
adb shell dumpsys package 包名 ->info.txt
获取应用包名
adb shell dumpsys window windows | grep mFocusedApp
或者
adb shell dumpsys window windows | findstr mFocusedApp

打开WiFi设置界面

1
adb shell am start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings

打开热点设置界面

1
adb shell am start -n com.android.settings/.TetherSettings

查询蓝牙是否开启

1
adb shell settings get global bluetooth_on

返回结果0代表关闭,1代表开启

1
adb shell dumpsys bluetooth_manager | findstr enabled

返回结果是true或者false,说明开启或关闭

查询WiFi是否开启

1
adb shell settings get global wifi_on

返回结果0代表关闭,1代表开启
查询蓝牙地址
adb shell settings get secure bluetooth_address
查询WiFi地址
adb shell cat /sys/class/net/wlan0/address
开启WiFi

1
adb shell svc wifi enable

关闭WiFi

1
adb shell svc wifi disable

打开蓝牙设置界面
adb shell am start -a android.settings.BLUETOOTH_SETTINGS
获取手机休眠时间
adb shell settings get system screen_off_timeout
更改手机休眠时间
adb shell settings put system screen_off_timeout 600000(10分钟)
获取系统默认输入法
adb shell settings get secure default_input_method
获取手机是否为自动亮度
adb shell settings get system screen_brightness_mode (0代表非自动,1代表为自动)
设置手机为自动调整亮度
adb shell settings put system screen_brightness_mode 1
获取手机当前亮度
adb shell settings get system screen_brightness
设置手机亮度(0-255)
adb shell settings put system screen_brightness 350

定位操作

打开定位设置界面

得先打开设置APP,然后再执行下面的命令:

1
adb shell am start -a android.settings.LOCATION_SOURCE_SETTINGS

开启定位

1
adb shell settings put secure location_providers_allowed +gps

关闭定位

1
adb shell settings put secure location_providers_allowed -gps

查看定位方式
adb shell settings get secure location_providers_allowed (前提是位置信息开启)
拨打电话
adb shell am start -a android.intent.action.CALL tel:8888888888888

发送短信
adb shell am start -a android.intent.action.SENDTO -d sms:10086(发送目的号码) –es sms_body “hello”(短信内容) –ez exit_on_sent true

获取应用包名
adb shell dumpsys window windows | findstr mFocusedApp

清除应用数据与缓存:
adb shell pm clear cn.com.test.mobile
启动应用:
adb shell am start -n cn.com.test.mobile/.ui.SplashActivity
停止应用
adb shell am force-stop cn.com.test.mobile
飞行模式
adb shell settings set global airplane_mode_on
(0==关闭,1==开启)
开启飞行模式
adb shell settings put global airplane_mode_on 1

手机震动测试(前提手机root)
adb shell echo ‘3000’>/sys/devices/virtual/timed_output/vibrator/enable

滑动点击

向上滑
adb shell input touchscreen swipe 930 880 930 380
向下滑
adb shell input touchscreen swipe 930 380 930 880
向右滑
adb shell input touchscreen swipe 330 880 930 880
向左滑
adb shell input touchscreen swipe 930 880 330 880
模拟鼠标点击操作
adb shell input mouse tap 100 500
长按
adb shell input swipe startX startY startX startY 500
滑动解锁
adb shell input swipe 300 1000 300 500
冷启动app
adb shell am start -W -n package/activity
热启动
①停止app
adb shell input keyevent 3 ②adb shell am start -W -n package/activity
查看内存占用情况
adb -s 设备号 shell top -m 进程数量 -n 数据的刷新次数 -s 按哪列进行排序 -d 刷新时间间隔(默认5秒)

切换手机电池为非充电状态
adb shell dumpsys battery set status 1
改变手机电量
adb shell dumpsys battery set level 58

获取当前电量
adb shell cat /sys/class/power_supply/battery/capacity

手机截屏

adb shell /system/bin/screencap -p /sdcard/screenshot.png

录制屏幕
adb shell screenrecord –time-limit 10 /sdcard/demo.mp4

获取手机型号

1
adb shell getprop ro.product.model

获取电池信息
adb shell dumpsys battery
获取屏幕分辨率
adb shell wm size
获取屏幕密度
adb shell wm density
显示屏参数
adb shell dumpsys window displays
获取手机IP地址
adb shell ifconfig | findstr Mask
查看WiFi局域网地址
adb shell ifconfig wlan0
显示区域位置
adb shell wm overscan 0,0,0,200 (四个数字分别表示距离左、上、右、下边缘的留白像素,以上命令表示将屏幕底部 200px 留白)
恢复原显示区域命令
adb shell wm overscan reset

获取USB调试模式
adb shell settings get global adb_enabled
关闭USB调试模式
adb shell settings put global adb_enabled 0

状态栏和导航栏的显示隐藏
adb shell settings put global policy_control key-values
key-values 可由如下几种键及其对应的值组成,格式为 key1=value1:key2=value2。
immersive.full———-同时隐藏
immersive.status———-隐藏状态栏
immersive.navigation———-隐藏导航栏
immersive.preconfirms———-?
这些键对应的值可则如下值用逗号组合:
apps———-所有应用
———-所有界面
packagename———-指定应用
-packagename———-排除指定应用
例如:
adb shell settings put global policy_control immersive.full=

表示设置在所有界面下都同时隐藏状态栏和导航栏。
adb shell settings put global policy_control immersive.status=com.package1,com.package2:immersive.navigation=apps,-com.package3
表示设置在包名为 com.package1 和 com.package2 的应用里隐藏状态栏,在除了包名为 com.package3 的所有应用里隐藏导航栏。

打开网页: adb shell am start -a android.intent.action.VIEW -d http://www.baidu.com

查看通信日志 :
adb logcat -b radio (常用于查看详细的通话状态)
获取界面控件:
adb uiautomator dump
列出输入法:
adb shell ime list -s

永不休眠:
adb shell settings put system screen_off_timeout 2147483647

关闭\打开自动旋转:
adb shell settings put system accelerometer_rotation 0\1

参考资料

https://blog.csdn.net/qq_28170363/article/details/108695746

adbui.bat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@echo off
setlocal EnableExtensions
@REM 进入当前盘符
%~d0
@REM 进入当前文件所在目录
cd %~dp0
@REM 执行命令,遍历命令的输出结果
@REM 命令的输出的第一行没有我们需要的设备序列号.
@REM 遍历的时候跳过第一行.
@REM 对遍历的每行以空白符进行分隔,取分隔得到的第1个字段作为循环变量的值.
@REM 如果存在多个设备的话,第1个字段就是该设备的序列号.
for /f "skip=1 tokens=1" %%i in ('adb devices -l') do (
echo -----------------------------------------
echo --------------------------
@REM 输出设备的序列号.
echo current device: %%i
echo --------------------------
@REM 遍历文件中的没一行,以空白符作为分隔符来分隔每一行,取每行的分割得到的一个字段作为循环变量的值.
@REM 文件中每行的第一个字段保存有我们要写在的APP的包名
for /f "tokens=1" %%k in (adbui.txt) do (
@REM 执行adb命令获取该设备上安装的所有第三方APP的包名.
@REM 遍历命令的输出结果,以冒号作为分割符来分割每一行,取分割后的第2段字符串作为循环变量的值.
for /f "tokens=2 delims=:" %%j in ('adb -s %%i shell pm list packages -3') do (
@REM 比较文件中的保存的第三方APP包名和设备中的安装的第三方APP的包名.
@REM 如果两者相等,则说明该包名的APP需要卸载。
if %%j == %%k (
echo uninstall: %%j
echo.
echo code: adb -s %%i uninstall %%j
@REM 执行adb命令,从该设备上根据包名卸载这个APP.
@REM 等真正执行的时候取消下面的注释即可.
adb -s %%i uninstall %%j
echo.
) else (
echo no uninstall: %%j
)

)
)
echo -----------------------------------------
)

问题描述

最近我在用idea写批处理脚本的时候遇到了一个很无语的bug。

我使用@REM在.bat文件中写了中文注释。在我运行的时候,程序会莫名其妙的输出一些乱码,并且提示这些乱码 不是内部或外部命令,也不是可运行的程序
或批处理文件。

批处理 中文注释 引起 “不是内部或外部命令,也不是可运行的程序或批处理文件。”bug

源代码

adbui5.bat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@echo off
setlocal EnableExtensions
@REM 进入当前盘符
%~d0
@REM 进入当前文件所在目录
cd %~dp0
@REM 执行命令,遍历命令的输出结果
@REM 命令的输出的第一行没有我们需要的设备序列号.
@REM 遍历的时候跳过第一行.
@REM 对遍历的每行以空白符进行分隔,取分隔得到的第1个字段作为循环变量的值.
@REM 如果存在多个设备的话,第1个字段就是该设备的序列号.
for /f "skip=1 tokens=1" %%i in ('adb devices -l') do (
echo -----------------------------------------
echo --------------------------
@REM 输出设备的序列号.
echo current device: %%i
echo --------------------------
@REM 遍历文件中的没一行,以空白符作为分隔符来分隔每一行,取每行的分割得到的一个字段作为循环变量的值.
@REM 文件中每行的第一个字段保存有我们要写在的APP的包名
for /f "tokens=1" %%k in (adbui.txt) do (
@REM 执行adb命令获取该设备上安装的所有第三方APP的包名.
@REM 遍历命令的输出结果,以冒号作为分割符来分割每一行,取分割后的第2段字符串作为循环变量的值.
for /f "tokens=2 delims=:" %%j in ('adb -s %%i shell pm list packages -3') do (
@REM 比较文件中的保存的第三方APP包名和设备中的安装的第三方APP的包名.
@REM 如果两者相等,则说明该包名的APP需要卸载。
if %%j == %%k (
echo uninstall: %%j
echo.
echo code: adb -s %%i uninstall %%j
@REM 执行adb命令,从该设备上根据包名卸载这个APP。
@REM 等真正执行的时候取消下面的注释即可。
@REM adb -s %%i uninstall %%j
echo.
) else (
echo no uninstall: %%j
)

)
)

echo -----------------------------------------
)

运行结果

运行的部分结果如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
PS G:\dev2\idea_workspace\MyJavaTools> adbui5
-----------------------------------------
--------------------------
current device: QWXNU18B27101030
--------------------------
no uninstall: com.quark.browser
no uninstall: com.jooan.qiaoanzhilian
uninstall: com.meta.box

code: adb -s QWXNU18B27101030 uninstall com.meta.box
'姝f墽琛岀殑鏃跺€欏彇娑堜笅闈㈢殑娉ㄩ噴鍗冲彲銆?' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

no uninstall: com.tencent.mobileqq
no uninstall: com.hunantv.imgo.activity
uninstall: com.m4399.gamecenter

code: adb -s QWXNU18B27101030 uninstall com.m4399.gamecenter
'姝f墽琛岀殑鏃跺€欏彇娑堜笅闈㈢殑娉ㄩ噴鍗冲彲銆?' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

no uninstall: com.android.chrome
no uninstall: com.tencent.qqlivepad
uninstall: com.wuba

code: adb -s QWXNU18B27101030 uninstall com.wuba
'姝f墽琛岀殑鏃跺€欏彇娑堜笅闈㈢殑娉ㄩ噴鍗冲彲銆?' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

no uninstall: com.microsoft.emmx
no uninstall: cn.wps.moffice_eng
-----------------------------------------
PS G:\dev2\idea_workspace\MyJavaTools>

解决:乱码

乱码的问题,是因为我用的编码是UTF-8编码,和Windows的编码不一致造成的,把文件的编码换成GBK后就可以解决。

解决:不是内部或外部命令,也不是可运行的程序或批处理文件。

经过都反复确认,我的语法并没有问题。删掉上面的注释后,乱码就消失的。可见问题出现在的注释上。

换成英文的注释,没有乱码,可见出现在中文的注释上。

解决方法:使用英文的标点符号

经过我的反复试错,我发现在注释中如果最后一个字符是中文,或者中文的标点符号,当你在末尾按下回车之后,接着写下一条注释的时候就会出现上述的问题。

把中文注释末尾的中文标点符号删掉,换成英文的标点符号就可以解决这个问题。

我把中文注释末尾的中文句号,换成英文的点号后就不会出现“不是内部或外部命令,也不是可运行的程序或批处理文件。”这样的提示信息了。

修改后的代码

adbui5.bat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@echo off
setlocal EnableExtensions
@REM 进入当前盘符
%~d0
@REM 进入当前文件所在目录
cd %~dp0
@REM 执行命令,遍历命令的输出结果
@REM 命令的输出的第一行没有我们需要的设备序列号.
@REM 遍历的时候跳过第一行.
@REM 对遍历的每行以空白符进行分隔,取分隔得到的第1个字段作为循环变量的值.
@REM 如果存在多个设备的话,第1个字段就是该设备的序列号.
for /f "skip=1 tokens=1" %%i in ('adb devices -l') do (
echo -----------------------------------------
echo --------------------------
@REM 输出设备的序列号.
echo current device: %%i
echo --------------------------
@REM 遍历文件中的没一行,以空白符作为分隔符来分隔每一行,取每行的分割得到的一个字段作为循环变量的值.
@REM 文件中每行的第一个字段保存有我们要写在的APP的包名
for /f "tokens=1" %%k in (adbui.txt) do (
@REM 执行adb命令获取该设备上安装的所有第三方APP的包名.
@REM 遍历命令的输出结果,以冒号作为分割符来分割每一行,取分割后的第2段字符串作为循环变量的值.
for /f "tokens=2 delims=:" %%j in ('adb -s %%i shell pm list packages -3') do (
@REM 比较文件中的保存的第三方APP包名和设备中的安装的第三方APP的包名.
@REM 如果两者相等,则说明该包名的APP需要卸载。
if %%j == %%k (
echo uninstall: %%j
echo.
echo code: adb -s %%i uninstall %%j
@REM 执行adb命令,从该设备上根据包名卸载这个APP.
@REM 等真正执行的时候取消下面的注释即可.
@REM adb -s %%i uninstall %%j
echo.
) else (
echo no uninstall: %%j
)

)
)

echo -----------------------------------------
)