0. 原理

上位机通过ADB打开下位机的相机应用,发送指令完成拍照,并将结果传至上位机。

1. 环境

上位机(Master)

设备 (从前线退至后方的高龄笔记本)Compaq Presario CQ45
CPU Intel Core 2 Duo T9400
内存容量 4GB
OS Ubuntu 20.04.3 LTS x86_64

Neofetch

下位机(Slave)

设备 伊拉克战损版 索尼(日本NTT DOHOMO特供) Xperia X Performance
CPU 高通 MSM8996
内存容量 8GB Slave的内存比Master大的确是个笑话
OS Android 8.0.0

上位机与下位机通过USB连接,下位机已开启USB调试

2. 部署ADB

1.1

1
sudo apt install adb

1.2 “找不到设备”

问题:

1
2
3
bkryofu@Hanekawa-Runba:~$ adb devices
List of devices attached

找不到设备。

解决:

执行lsusb得到设备ID。

1
2
3
4
5
6
7
8
9
10
bkryofu@Hanekawa-Runba:~$ lsusb
Bus 002 Device 024: ID 0fce:51e1 Sony Ericsson Mobile Communications AB SO-04H
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

编辑(新建) /etc/udev/51-android.rules,加入:

1
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fce", ATTRS{idProduct}=="51e1",MODE="0666",GROUP="plugdev"

idVendor为冒号前的数字,idProduct为冒号后的数字。

编辑(新建)~/.android/adb_usb.ini,加入0x0fce,也就是加上十六进制数前缀的idVendor

重启adb。

1
2
3
sudo service udev restart  
sudo adb kill-server
sudo adb start-server

测试:

1
2
3
bkryofu@Hanekawa-Runba:~$ adb devices
List of devices attached
CB512ARAR9 device

至此,ADB就部署完了。

3. 测试

参考python+adb 控制安卓手机拍照并传电脑_lawup的博客-CSDN,依次执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
adb shell input keyevent 224

# 启动相机
adb shell am start -a android.media.action.STILL_IMAGE_CAMERA

# camera键 拍照
adb shell input keyevent 27

# back键 暂退相机
adb shell input keyevent 4
# ————————————————
# 版权声明:本文为CSDN博主「lawup」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/lawup/article/details/105510613

无效的keyevent 27

问题

通过ADB可以成功唤醒下位机屏幕并启动相机,但出现的问题是拍照键的键值无法控制相机应用。

经过测试,在索尼爱立信LT18i上会有同样的症状,而在我自己的手机上是可以通过发送keyevent 27按键指令来拍照的。

不愧是用心做技术,用脚做优化的索尼啊……

解决

adb shell input命令不止可以模拟按键,还可以模拟触摸。命令是adb shell input tap <x> <y>

那么,只要确定相机UI拍照键的坐标,就可以了。

开启下位机的开发者模式中的指针位置,在ADB发送指令进行截图。

延迟三秒截图,与此同时,按住相机APP的快门键直至截图完毕。

1
2
3
bkryofu@Hanekawa-Runba:~$ adb shell input keyevent 224
bkryofu@Hanekawa-Runba:~$ adb shell am start -a android.media.action.STILL_IMAGE_CAMERA
bkryofu@Hanekawa-Runba:~$ sleep 3 && adb shell /system/bin/screencap -p /storage/emulated/0/screenshot.png

上传截图。

1
2
bkryofu@Hanekawa-Runba:~$ adb pull /storage/emulated/0/screenshot.png
/storage/emulated/0/screenshot.png: 1 file pulled. 13.6 MB/s (1377730 bytes in 0.097s)

传回:

截图(把水印忽略了吧,那是程序自动加的)

得出坐标(539, 1605)是快门键的坐标。

拍照

启动相机后,执行:

1
adb shell input tap 539 1605

图片会默认保存在/storage/emulated/0/DCIM/100ANDRO,将该目录中的文件上传至上位机。

1
adb pull /storage/emulated/0/DCIM/100ANDRO/ .

效果:

布满灰的床头柜

4. 整合为脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

# 删除图片目录中的照片(之后有需要)
adb shell rm -rf /storage/emulated/0/DCIM/100ANDRO/*
# 唤醒
adb shell input keyevent 224
# 打开相机APP
adb shell am start -a android.media.action.STILL_IMAGE_CAMERA
# 延迟两秒,防止死机
sleep 2
# 拍照
adb shell input tap 539 1605
# 延迟五秒,等待照片生成
sleep 5
# 退出并熄屏
adb shell input keyevent 4
adb shell input keyevent 26
# 上传照片
adb pull /storage/emulated/0/DCIM/100ANDRO/ .
# 删除原目录中的照片
adb shell rm -rf /storage/emulated/0/DCIM/100ANDRO/*
mv 100ANDRO/* .
rm -rf 100ANDRO/

参考