Kivy只是一个图形库,在Android平台上,有很多功能需要自己扩展,其中如何监听SD卡或者U盘的插拔事件就是一个问题。但是实际上解决起来也还是比较简单。
在Android平台上,用vold来替代linux下的udev来进行热插拔设备的管理。通过local socket server把热插拔设备的事件广播给正在监听的设备,所以要在Kivy中获取U盘或者SD卡的事件,只需要通过local socket client来监听vold的发送的事件,监听的路径为/dev/socket/vold,具体的实现方式如下:
import socket import select s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.connect('/dev/socket/vold') print 'start select!' while True: ss = select.select([s,],[],[],20) data = s.recv(1024) for msg in data.split('\x00'): print msg
'605 Volume sdcard /sdcard state changed from 2 (Pending) to 1 (Idle-Unmounted)'
'630 Volume sdcard /sdcard disk inserted (253:0)'
'605 Volume sdcard /sdcard state changed from 1 (Idle-Unmounted) to 3 (Checking)'
'605 Volume sdcard /sdcard state changed from 3 (Checking) to 4 (Mounted)'
当拔下SD卡时,会得到下面的打印:
'605 Volume sdcard /sdcard state changed from 4 (Mounted) to 5 (Unmounting)'
'605 Volume sdcard /sdcard state changed from 5 (Unmounting) to 1 (Idle-Unmounted)'
'631 Volume sdcard /sdcard disk removed (253:0)'
'605 Volume sdcard /sdcard state changed from 1 (Idle-Unmounted) to 0 (No-Media)'
'605 Volume sdcard /sdcard state changed from 0 (No-Media) to 2 (Pending)'
具体的代码的意义可以看system/vold/ResponseCode.h,如:
static const int VolumeDiskInserted = 630;
static const int VolumeDiskRemoved = 631;
static const int VolumeStateChange = 605;
要监听SD卡的挂载事件可以解析如下的字符串:
'605 Volume sdcard /sdcard state changed from 3 (Checking) to 4 (Mounted)'
要监听SD卡的拔出事件可以解析如下的字符串:
'605 Volume sdcard /sdcard state changed from 4 (Mounted) to 5 (Unmounting)'
具体的解析字符串的工作比较简单,可以用正则表达式来进行解析。
但是如果你直接在Kivy下执行上面的代码,会发现socket.AF_UNIX未定义,具体的原因可以看:
https://github.com/kivy/python-for-android/issues/163
目前的解决方法是直接在pyconfig.h中定义HAVE_SYS_UN_H
,然后再重新编译python。