20

我有一台数码单反相机和一台运行 Android Honeycomb 的三星 Galaxy Tab。DSLR 使用 USB 电缆连接到平板电脑(通过 USB 套件在平板电脑上启用主机功能)。我希望在用户使用此外部相机拍照时收到通知,以便将此图像下载到平板电脑或对其执行其他操作,例如显示包含从图像中获取的元信息的 Toast 通知。

据我所知,所有现有工具(例如FileObserver使用底层inotify机制MediaContentProvider等)都允许监视更改,要求监视特定文件或文件系统路径。这已经足够好了,直到我们在 2.x 和更早的 Android 版本中获得块层协议支持 - 当您连接设备时,它已安装在设备文件系统的某个位置,您可以将此安装点用作这些工具的观察点.

由于 Honeycomb Google 已将访问外部 USB 设备的方式更改为Media Transfer ProtocolwithPTP作为其子集。现在,当我将外部 USB 设备连接到 Android 设备时,我不会看到它的任何挂载点(我正在使用adb shell后续mount命令来获取它们)。此外,MTP实现使用的存储 id 显然充当更高级别的抽象,并且只是普通的整数值。我希望有一种方法可以以某种方式将这些存储 id 转换为真实路径/挂载点/任何东西,但显然似乎没有。

考虑到MediaScanner已经在我的设备上运行的 Android,我猜想它可以Intent在设备可访问的媒体文件发生变化时通过特殊广播来解决这个问题,所以我开始寻找已经存在并适合Intents被通知的问题,但没有运气- 我发现只有在分别连接和断开设备时才广播ACTION_MEDIA_MOUNTEDACTION_MEDIA_REMOVED这意味着MediaScanner在您重新安装之前无法注意到设备上的任何更改(我已经使用股票图库应用程序仔细检查了它 - 在您拔下然后将其插入 Android 设备之前,它不会在相机上看到任何新创建的图像再次)。

试图为外部 sdcard 获取这个挂载路径,我使用Environment.getExternalStorageDirectory()了 API 调用,但它产生了模拟 Galaxy 的 sdcard 路径,而/mnt/sdcard不是相机的路径。所以它对我也不起作用。

我设法解决了这个问题,只是在启动定期Timer事件并AsyncTask充当TimerTask. 此任务确实初始化 USB 连接,打开设备,扫描整个设备内存,仅获取最后拍摄的照片,然后关闭设备描述符和 USB 连接。

考虑到它必须每次都执行所有这些操作,这看起来不是最好和最有效的方法,这可能非常频繁,比如每 5 或 10 秒。它肯定会很快耗尽电池电量并产生不必要的系统 I/O,仅用于拍摄最后一张照片并将其与上一张照片进行比较(99% 是相同的图像),但我还没有找到更好的工作解决方案这样做。最好有一个带有基于事件的通知的观察者机制。

所以我的问题是,有没有更有效的方式来通知 Honeycomb 或更高版本的 Android 的外部 USB 存储的变化,而不是上面描述的?

4

1 回答 1

2

如果您想要一种更有效的方式,相机必须通过 USB 发送某种信号,表明它已拍摄照片。我想它没有这样做。

因此,您必须按照您描述的方式手动检查:

挂载存储->检查更改->对检测到的更改执行您的操作。

我不知道您以前读过什么“MTP 方式”,但这里有一个示例应用程序:

https://github.com/ynakanishi/Honeycomb-MTP-sample

为了不每次都扫描整个存储,您可以保存读取文件名的结果,例如每次检查并比较它以查找新文件名时。通常文件的命名也以相机上的相同数字开头。因此,如果您使用空 sd 卡开始会话,您已经知道照片将具有的文件名。让我们说img0001.jpg。所以你只需要编写一个函数来抓取该文件,直到它成功。如果您想要下一个 img0002.jpg,您可以编写一个任务/服务/函数来抓取该文件,直到成功,依此类推。

如果您想节省电池电量,您可以在中间安装一个额外的电池/电源来为 USB 端口供电。

您可以尝试使用 ScheduledExecutorService 来代替 Async 任务或 timerTask,看看它是否使用更少的电量。

希望能给你一些新的想法

于 2012-09-25T08:01:43.103 回答