当 SDK 中缺少导入的 class 时,Android 项目如何编译?

How can Android project compile when imported class is missing in SDK?

好吧,也许它很简单,但我现在想不通。

我已经在 Android Studio 1.5.1 中导入了 google 示例项目 Card Reader,它在 compileSdkVerison 23 编译,它可以在我的手机上运行。

然后我把SDK绕了一遍源码到android.nfc.tech.BasicTagTechnology,发现android.nfc.tech.BasicTagTechnology#transceive里面的TransceiveResult无法解析,然后发现class TransceiveResult 在我的 D:\Android\sdk\platforms\android-23\android.jar 中丢失,但在 Android 源代码中出现 D:\Android\sdk\sources\android-23\android\nfc\TransceiveResult.java 然后我意识到它可以隐藏在 public 中,而不是导出,实际上这是

/**
 * Class used to pipe transceive result from the NFC service.
 *
 * @hide
 */

public final class TransceiveResult implements Parcelable

然后我做了一些随机的事情,在我同步项目后,清理并重建,使缓存无效/重新启动,仍然无法解决 TransceiveResult 顺便说一句,我想知道因为符号已经在SDK中迷路了,项目如何顺利编译?

编辑我终于啊哈

我们在代码中调用android.nfc.tech.BasicTagTechnology#transceive而不是TransceiveResult,在编译时我们不需要解析TransceiveResult,我们只需要解析android.nfc.tech.BasicTagTechnology#transceive在我们的代码中引用了,那一刻我迷路了。

@hide 表示它没有包含在文档中,如 here 所述,它也从编译中使用的 android.jar 中的 类 中删除。 然而,这些将在 运行 时间内可用。

更新: 为了在您的 IDE 中澄清,当您深入研究您的 SDK 类 时,您可能会看到对您无法解析的隐藏成员的引用。这没关系,只要它们在 SDK 类 中而不是在您的代码中,它仍然会编译。

如果你想使用那些隐藏的 classes/methods/fields 你有两个主要选择:

1) 获取 android-framework.jar 的完整版本并能够编译。然而,这有一个缺点,编译代码可能不会 运行 在其他 Android 版本中,因为 Class 或者方法可能甚至不存在。 并且例如 BasicTagTechnology 实际上是包私有的,所以你无论如何都不能访问它

2) 使用反射:

Class tr = Class.forName("android.nfc.TransceiveResult");
        Constructor constructor =
                tr.getConstructor(new Class[]{int.class, byte[].class});
        Object trObj = constructor.newInstance(1, new byte[]{1,2});

这是一个更好的选择,因为它更灵活,您可以检查 class/method 是否存在于 init/call 它们,捕获异常等。