Android 设备选择器中的序列号/名称

3
如果我在Eclipse中进行开发,我经常会按绿色的“运行”按钮。一个名为“Android设备选择器”的弹出窗口出现,让我从连接的设备列表中选择。一般情况下没有问题,因为任何手机都会显示出来。我注意到“序列号”列有两种不同的显示方式:
通常它只显示序列号,但有时设备名称,例如“Asus Nexus 7”,也会显示出来。这非常有帮助,特别是如果您有多个设备要测试,并且您不能(或不想)记住所有这些序列号(如果您有多个使用著名序列号“0x0123456789ABCDEF”的设备,则更加混乱)。
我不知道为什么和何时Eclipse会显示设备名称,但我想找到一种方法来强制Eclipse收集这些设备名称而不是它们的序列号,并在设备选择器中显示它们。
1个回答

3

请查看源代码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/system/build.prop中包含ro.product.manufacturerro.product.model,您可以使用adb -e shell getprop|grep "\[ro.product"命令查看当前值。
[ro.product.manufacturer]: [samsung]
[ro.product.model]: [GT-I9100]

在DDMS视图中显示的设备名称/序列号为samsung-gt_i9100-0x0123456789ABCDEF。请注意,一些不良的厂商无法正确设置这两个属性,因此对于这些设备,只会显示序列号。

Eclipse中没有任何配置可以让您简单地勾选并强制显示它。如果您的设备已经root,您可以编辑这些属性,以便在DDMS视图中正确显示设备的制造商和型号,例如使用adb shell setprop <key> <value>或直接编辑文件系统中的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将无法正常获取属性。

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


非常有帮助,感谢您的见解。让我仍然想知道的是,为什么它们有时会显示正确的(设备名称),而在同一台设备上(也许10分钟后),我只会得到序列号,如果eclipse只是获取系统属性。 - Rafael T
@RafaelT,是的,我明白了。请查看我对故事第二部分的编辑。 - yorkw
太棒了。这正是我在寻找的。再次感谢您详细的解释 :) - Rafael T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接