【问题标题】:Serial Number/Name in Android Device ChooserAndroid 设备选择器中的序列号/名称
【发布时间】:2012-10-01 08:04:59
【问题描述】:

如果我在 Eclipse 中开发,我经常按下绿色的run 按钮。出现一个名为Android Device Chooser 的弹出窗口,让我从连接的设备列表中进行选择。一般来说,这没有问题,因为任何电话都会出现。我刚刚观察到Serial Number 列显示了两个不同的内容:

通常它只显示序列号,但有时会显示设备名称,即Asus Nexus 7。这非常有帮助,特别是如果您有多个设备要测试,并且您不能(或不会)记住所有这些序列(如果您有多个设备与著名的序列 0x0123456789ABCDEF )。

我不知道eclipse为什么以及何时显示设备名称,但我想找到一种方法来强制eclipse收集这些设备名称而不是它们的序列并在设备选择器中显示它们.

【问题讨论】:

    标签: java android eclipse development-environment adt


    【解决方案1】:

    查看来源com.android.ddmlib.Device 了解 DDMS 如何生成设备名称/序列号:

    private static final String DEVICE_MODEL_PROPERTY = "ro.product.model"; //$NON-NLS-1$
    private static final String DEVICE_MANUFACTURER_PROPERTY = "ro.product.manufacturer"; //$NON-NLS-1$
    
    ... ...
    
    private static final char SEPARATOR = '-';
    
    ... ...
    
    @Override
    public String getName() {
        if (mName == null) {
            mName = constructName();
        }
    
        return mName;
    }
    
    private String constructName() {
        if (isEmulator()) {
            String avdName = getAvdName();
            if (avdName != null) {
                return String.format("%s [%s]", avdName, getSerialNumber());
            } else {
                return getSerialNumber();
            }
        } else {
            String manufacturer = cleanupStringForDisplay(
                    getProperty(DEVICE_MANUFACTURER_PROPERTY));
            String model = cleanupStringForDisplay(
                    getProperty(DEVICE_MODEL_PROPERTY));
    
            StringBuilder sb = new StringBuilder(20);
    
            if (manufacturer != null) {
                sb.append(manufacturer);
                sb.append(SEPARATOR);
            }
    
            if (model != null) {
                sb.append(model);
                sb.append(SEPARATOR);
            }
    
            sb.append(getSerialNumber());
            return sb.toString();
        }
    }
    
    private String cleanupStringForDisplay(String s) {
        if (s == null) {
            return null;
        }
    
        StringBuilder sb = new StringBuilder(s.length());
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
    
            if (Character.isLetterOrDigit(c)) {
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append('_');
            }
        }
    
        return sb.toString();
    }
    

    如果您想了解 DDMS 如何呈现此设备名称/序列号,请参阅com.android.ddmuilib.DevicePanel

    ro.product.manufacturerro.product.model/system/build.prop,可以使用@987654326 @查看当前值:

    [ro.product.manufacturer]: [samsung]
    [ro.product.model]: [GT-I9100]
    

    那么 DDMS 透视图中显示的设备名称/序列号为 samsung-gt_i9100-0x0123456789ABCDEF。请注意,一些设备供应商没有正确设置这两个属性,这就是为什么对于那些设备,它只显示序列号。

    Eclipse 中没有配置可以让您简单地勾选并强制显示。如果您的设备已root,您可以编辑这些属性,以便设备的制造商和型号在DDMS 透视图中正确显示,例如,使用adb shell setprop &lt;key&gt; &lt;value&gt; 或直接在文件系统中编辑build.prop。


    DDMS 深入

    DDMS获取设备信息的方式比较复杂,一般来说,当AndroidDebugBridge启动并运行时,它会在单独的线程中启动一个DeviceMonitor,不断监听设备连接并发出远程shell命令getprop到查询设备信息的具体设备如ro.product.manufacturerro.product.model,这个远程shell命令执行不可靠(可能受多种因素影响),也不保证一直抓取属性。见com.android.ddmlib.DeviceMonitor:

    /**
     * Queries a device for its build info.
     * @param device the device to query.
     */
    private void queryNewDeviceForInfo(Device device) {
        // TODO: do this in a separate thread.
        try {
            // first get the list of properties.
            device.executeShellCommand(GetPropReceiver.GETPROP_COMMAND,
                    new GetPropReceiver(device));
    
            queryNewDeviceForMountingPoint(device, IDevice.MNT_EXTERNAL_STORAGE);
            queryNewDeviceForMountingPoint(device, IDevice.MNT_DATA);
            queryNewDeviceForMountingPoint(device, IDevice.MNT_ROOT);
    
            // now get the emulator Virtual Device name (if applicable).
            if (device.isEmulator()) {
                EmulatorConsole console = EmulatorConsole.getConsole(device);
                if (console != null) {
                    device.setAvdName(console.getAvdName());
                }
            }
        } catch (TimeoutException e) {
            Log.w("DeviceMonitor", String.format("Connection timeout getting info for device %s",
                    device.getSerialNumber()));
    
        } catch (AdbCommandRejectedException e) {
            // This should never happen as we only do this once the device is online.
            Log.w("DeviceMonitor", String.format(
                    "Adb rejected command to get  device %1$s info: %2$s",
                    device.getSerialNumber(), e.getMessage()));
    
        } catch (ShellCommandUnresponsiveException e) {
            Log.w("DeviceMonitor", String.format(
                    "Adb shell command took too long returning info for device %s",
                    device.getSerialNumber()));
    
        } catch (IOException e) {
            Log.w("DeviceMonitor", String.format(
                    "IO Error getting info for device %s",
                    device.getSerialNumber()));
        }
    }
    

    注意device.executeShellCommand() 抛出并由DeviceMonitor.queryNewDeviceForInfo() 处理的所有异常,如果发生任何这些异常,DDMS 将无法正确获取属性。

    如果您想阅读完整的源代码,请查看here

    【讨论】:

    • 帮助很大,感谢您的见解。让我仍然想知道的是为什么它们有时会显示正确(设备名称),并且在同一个设备上(可能 10 分钟后)我只是得到序列号,如果 eclipse 只是抓住了 system.property
    • @RafaelT,是的,我明白了。查看我对故事第二部分的编辑。
    • 太棒了。这正是我想要的。再次感谢您的深入解释:)
    猜你喜欢
    • 2016-11-04
    • 1970-01-01
    • 2014-12-18
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    相关资源
    最近更新 更多