【问题标题】:How can I retrieve an SD card's serial number in Android 7.0+?如何在 Android 7.0+ 中检索 SD 卡的序列号?
【发布时间】:2017-09-15 00:34:44
【问题描述】:

注意:这个问题是关于物理 SD 卡的序列号,而不是已安装的 volume 的 UUID。这是两个独立的数据。

在某些版本的 Android 和其他 Linux 变体中,可以获得已安装 SD 卡的序列号,例如通过阅读/sys/class/mmc_host/mmc0/mmc0:0001/serial/sys/block/mmcblk0/device/serial 的内容(具体数字可能会有所不同)。在我的测试中,只要将 SD 卡插入内置 SD 卡插槽(不是通过 USB 适配器安装),它就可以非常可靠地工作。

但从 Android 7.0 Nougat 开始,OS is said to be blocking access 到此信息,至少在某些设备上是这样。我通过在新的 Alcatel A30 GSM (Android 7.0) 上运行测试应用程序对此进行了测试,实际上上述方法因权限错误而失败:

java.io.FileNotFoundException: /sys/block/mmcblk0/device/serial (Permission denied)
at java.io.FileInputStream.open(Native Method)

为了将来参考,我们(从 adb shell 进行测试)对ls -ld 具有以下权限:

  • /sys/class/mmc_host 但不是 /sys/class/mmc_host/mmc0
  • /sys/block 但不是/sys/block/mmcblk0

由于上述方法不再有效,

  • Android 7.0 或更高版本是否有其他方法可以获取已挂载的 SD 卡的序列号?

  • 如果没有,Google 是否有任何文档或其他声明说明提供或不提供此功能的计划?我在 Android issue tracker 中没有找到任何东西,但可能我搜索的不对。

为了确保问题清楚,我说的是在非 root 设备上运行的普通(非系统)应用程序可以做什么,以及应用程序通常可以请求和接收的任何权限。

仅供参考,/sbin 目录似乎不可读,所以像 /sbin/udevadm 这样的命令不是一个选项。

【问题讨论】:

  • 我唯一能想到的就是getUuid() on StorageVolume。您将从StorageManager 获得StorageVolume 对象。但是,我不知道 UUID 是否与序列号有关。
  • 为了将来参考,这里是结果: 我测试它的设备给出的 UUID 为 76DE-3B41... 值得注意的是它只有 8 位数字。这是针对序列号为000fec46 的芯片。当我们使用不同的芯片调用 getUuid() 时,音量 UUID没有改变。所以UUID肯定不是芯片序列号。 @Commonsware 感谢您的想法……这比我以前得到的信息更多。
  • @LarsH 我怀疑这些是 selinux 配置的变化,我在这里转发了你的问题:issuetracker.google.com/issues/37091475
  • @marcinj:仅供参考,我在issuetracker.google.com/issues/37705442 创建了一个单独的错误报告,以关注这个范围更窄的问题,从而希望避免打开这么多关于安全性的蠕虫。
  • @LarsH 我已经把它变成了一个答案,并将我找到的所有信息都放在上面。我还计划在您的错误报告中添加评论。

标签: android sd-card serial-number


【解决方案1】:

对于那些在 Android 下查看 UUID 或 FAT 类型卷的卷序列号的人来说,仅供参考:一些 Fujifilm 相机,包括 X-T30(固件 1.10)在格式化时不会将卷序列号写入 FAT 卷。

在 Windows 下,CHKDSK 根本不显示卷序列号。 在 Android 上,调用 StorageVolume.getUuid() 返回“0000-0000”。

这一切都很好,很漂亮,直到您在 Android 上通过集线器安装两张 Fujifilm 格式的卡。然后似乎出现了身份冲突,Android 操作系统提示用户格式化其中一张卡。它们可以单独访问。

我猜这里有两个综合问题: 1) Fujifilm 在格式化时没有写入卷序列号,并且 2) Android 使用卷序列号作为挂载点路径的一部分,导致冲突。

Fujifilm 和 Google 可能都想关注这个问题。

编辑:在尼康 D810 中格式化的卡也有同样的问题,没有卷序列号。

【讨论】:

  • 了解这一点很有帮助。然而,这不是这个问题的答案,它是关于如何获取 SD 卡的序列号。挂载卷的 ID 与 SD 卡的序列号完全分开(见评论stackoverflow.com/questions/43484564/…)。
  • 啊。我的错。请注意,FAT 标准中包含“UUID”的字段(显然不是真正唯一的,因此用词不当)称为卷序列号(尽管它显然不是序列号,只是一个随机的,希望是伪唯一的 ID)。
  • 你说得对,它有时被称为“序列号”。我并不是说这个词是错误的。它与 SD 卡序列号只是不同的东西。重新格式化媒体时,卷 UUID 可以更改,但 SD 卡序列号不应更改。
【解决方案2】:

adb shell cat /sys/class/mmc_host/mmc1/mmc1:*/cid

你也可以试试

sudo hwinfo --disk

获取有关磁盘的信息,包括 SD 卡。

也试试

sudo hdparm -I /dev/sdb | more

【讨论】:

  • 第一个建议就像问题中提到的那样不起作用,但使用cid 而不是serial。它遇到同样的问题:/sys/class/mmc_host/mmc* 不可读。我会尽可能在 Android 7.0 上尝试其他两个建议,但是当我在 6.0 的 adb shell 下尝试它们时,找不到 sudohwinfohdparm
  • 我在 Android 7.0 设备上尝试了最后两个建议,得到了相同的结果——找不到 sudohwinfohdparm
【解决方案3】:

在 Android N 中,对 /sys nad /proc 的访问受到显着限制,这样做是为了在应用程序运行时提供更严格的沙箱。这在https://issuetracker.google.com/issues/37091475 中被解释为故意的。实际上并不是说 /sys 中的所有数据都无法访问,并且 Google 允许从该位置访问其他文件:

如果您认为 /sys 中有特定文件应该可供应用程序使用,但实际上没有,请提交一个可以评估请求的新错误。例如,/sys/devices/system/cpu 对所有进程都可用,因此说所有 /sys 都受到限制是不准确的。

我有一种不好的感觉,谷歌正在做出类似于苹果的改变,不允许获得硬件 id-s。如果这没有解决,那么解决方案是使用 google 帐户 ID。但我知道这并不总是可能的,并且需要对业务逻辑(许可等)进行重大更改。

希望您的bug report 会被积极考虑。

我发现的另一个相关 SO:File system changes in Android Nougat

【讨论】:

  • 感谢您的错误报告:您说的正是需要说的。
  • 您能告诉我您在哪些 Android 7 设备上遇到过此问题吗?我唯一可以使用的 Nougat 设备是我上面提到的阿尔卡特 A30,我想知道这个问题有多普遍。
  • 我们目前只在 Sony Z5 上看到过这种情况。
  • 我在索尼开发者论坛上添加了问题,也许他们会在这个话题上给出一些官方回应:talk.sonymobile.com/t5/General-Discussion/…
  • 仅供参考,对于我的澄清请求或您对我提交的 Android 问题的评论,我没有收到任何答复。所以我提交了一个新的文件,开头明确提到“如果您认为 /sys 中有特定文件应该可供应用程序使用,但不是,请提交一个可以评估请求的新错误。”:issuetracker.google.com/issues/38492944
【解决方案4】:
public String getSDCARDiD()
{
    String sd_cid = null;
    try {

        File file = new File("/sys/block/mmcblk1");
        String memBlk;
        if (file.exists() && file.isDirectory()) {

            memBlk = "mmcblk1";
        } else {
            //System.out.println("not a directory");
            memBlk = "mmcblk0";
        }

        Process cmd = Runtime.getRuntime().exec("cat /sys/block/"+memBlk+"/device/cid");
        BufferedReader br = new BufferedReader(new InputStreamReader(cmd.getInputStream()));
        sd_cid = br.readLine();
        //System.out.println(sd_cid);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return sd_cid;
}

试试这个:参考原始链接:Android get id of SD Card programmatically

【讨论】:

  • 这似乎是在检索设备 ID、SIM 序列号和 Android ID——这些都不是 SD 卡序列号。您是否有迹象表明这实际上会检索 SD 卡序列号?
  • 我已经按照这个链接编辑了我的答案,并且我更新了上面的代码。 stackoverflow.com/questions/9063161/… 归功于:stackoverflow.com/users/1408418/awcroper
  • 这基本上是我在问题第一段中描述的方法,从 Android 7 开始不再有效。CID 包括序列号。 serialcid 都无法读取,因为 /sys/block/mmcblk0(或 /sys/block/mmcblk1 视情况而定)无法读取。
  • 您要使用哪种设备进行测试?
  • 见问题的第二段。
【解决方案5】:

在您从 StorageManager 获得的 StorageVolume 上使用 StorageVolume.getUuid()

该值是在格式化卡时分配的卷 ID,其长度/格式因文件系统类型而异。对于 FAT32 它是 XXXX-XXXX,对于 NTFS 它是更长的十六进制字符串,对于内部大容量存储它返回 null。

【讨论】:

猜你喜欢
  • 2018-10-03
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多