Android UserManager.isUserAGoat() 的适当使用场景是什么?

4008
我在查看Android 4.2中引入的新API时,注意到了UserManager类中的以下方法:
public boolean isUserAGoat()

Used to determine whether the user making this call is subject to teleportations.

Returns whether the user making this call is a goat.

这应该如何使用?何时使用?


9
"If" 可以用来避免一些Java警告,作为彩蛋并测试谁读取了API。它也是对Chrome中一个彩蛋的参考。 - Dorian
17
这可能与谷歌在他们位于山景城总部的草坪上使用山羊作为割草机有关。您可以查看谷歌博客上有关此话题的文章链接。 - John Isaiah Carmona
5
由于某种原因,Googlers似乎喜欢山羊,难怪他们把它变成了复活节彩蛋。此外,还有一个认真的投资方向是山羊:据谷歌博客所述 - 山羊除草 - [山羊是“咩”的] (http://googleblog.blogspot.com/2010/04/goats-are-baaaahk.html),并在[youtube](http://www.youtube.com/watch?v=Jw_XI0WVZBg)上记录。毕竟,它们是本地草坪修剪机,而且效率高。 - none
31
在Android开发中,重力常数有一些有趣的命名,比如第一颗死星的重力常数(GRAVITY_DEATH_STAR_I)和电视剧《迷失》中的岛屿重力常数(GRAVITY_THE_ISLAND),后者当然是指“数字”。请参考http://developer.android.com/reference/android/hardware/SensorManager.html#GRAVITY_DEATH_STAR_I和http://developer.android.com/reference/android/hardware/SensorManager.html#GRAVITY_THE_ISLAND。 - Fernando Gallego
15
即使在Lollipop版本之后,他们也更新了文档:"从LOLLIPOP开始,此方法现在可以使用先进的山羊识别技术自动识别山羊。" - Patrick
显示剩余3条评论
12个回答

1990

Android R 更新:

从 Android R 开始,该方法始终返回 false。Google 表示这样做是为了"保护山羊隐私"。

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
 * now automatically identify goats using advanced goat recognition technology.</p>
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#R}, this method always returns
 * {@code false} in order to protect goat privacy.</p>
 *
 * @return Returns whether the user making this call is a goat.
 */
public boolean isUserAGoat() {
    if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R) {
        return false;
    }
    return mContext.getPackageManager()
            .isPackageAvailable("com.coffeestainstudios.goatsimulator");
}

之前的答案:

根据他们的source,在API 21之前,使用的方法是返回false

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 * @return whether the user making this call is a goat 
 */
public boolean isUserAGoat() {
    return false;
}

看起来这个方法对我们开发者来说没有实际用处。有人之前说过它可能是一个彩蛋

在API 21中,该实现已更改为检查是否安装了包名为com.coffeestainstudios.goatsimulator的应用程序。

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
 * now automatically identify goats using advanced goat recognition technology.</p>
 *
 * @return Returns true if the user making this call is a goat.
 */
public boolean isUserAGoat() {
    return mContext.getPackageManager()
            .isPackageAvailable("com.coffeestainstudios.goatsimulator");
}

这里是sourcechange

116
理论:山羊被发现出现在各种危险的地方,比如垂直悬崖,可能是因为它们不像常规非山羊用户那样遵循常规位置趋势。这可能解释了“瞬移”的现象,即当软件试图使用设计给非山羊用的算法确定它们的位置时,山羊看起来会突然出现在别的地方。 - tedders
13
@LarsH - 这是其中一个来源。 - djechlin
63
这是一堂历史课,而不是答案。即使它是复活节彩蛋,它是否有有效的使用情况?作为复活节彩蛋并不意味着它不能有用,而您也没有显示它是否有用。 - casperOne
48
这是一个真正的应用程序 - Kevin Krumwiede
233
我为那些自以为聪明地使用这个功能、期望它永远返回“false”的人感到难过。 - Martin Konecny
显示剩余7条评论

1038

我不知道这是否是“官方”用例,但以下代码在Java中会产生警告(如果与return语句混合使用,则可能会导致编译错误,从而导致无法访问的代码):

我不确定这是否是“官方”用例,但以下代码在Java中会产生警告(如果与return语句混合使用,则可能会导致编译错误,从而导致无法访问的代码):

while (1 == 2) { // Note that "if" is treated differently
    System.out.println("Unreachable code");
}

然而,这是合法的:

while (isUserAGoat()) {
    System.out.println("Unreachable but determined at runtime, not at compile time");
}

因此我经常会编写一个愚蠢的实用方法来快速虚拟出一个代码块,以便在完成调试后找到所有对它的调用,只要实现不改变,就可以用于这个目的。

JLS 指出 if (false) 不会触发“无法访问的代码”错误,原因是这会破坏对调试标志的支持,也就是说基本上是这种用例(参考 @auselen)。 (例如,static final boolean DEBUG = false;)。

我将 while 替换为 if,从而产生了一个更加晦涩的用例。我认为你可以利用这种行为使你的 IDE(如 Eclipse)出现问题,但是这个编辑已经是未来的 4 年了,我没有 Eclipse 环境可以测试。


12
我不确定这是否仅适用于Android,在标准的Java中,if(false){...}编译得很好(使用OpenJDK javac 1.6和1.7)。 - josefx
11
如果您特别要测试一个代码分支,其中if语句为false或true,那么这是模拟的最精确和明显的方法。如果您注释掉代码块,可能会不够准确,如果您没有匹配到正确的代码块结尾(也许您没注意到紧随其后的离散if/else代码块),它还会导致编译错误,如果您强制执行以下的"else"块等。 - djechlin
201
“如果实现方式不改变” - 这就是问题所在。这是一种灾难性的实现“if (false)”而无需警告,因为实现可能会发生变化。请参考我对这个问题的答案:从API21开始,如果用户安装了特定应用程序,“isUserAGoat()”将返回true。祝你好运,在“随机”设备上代码突然开始表现异常时诊断它! - Mark Whitaker
22
或者如果山羊开始使用设备。 - thedayturns
19
如果山羊开始使用安卓设备,那么这将是我们问题中最不值得关注的一点。 - Szymon Drosdzol
显示剩余6条评论

804

这似乎是谷歌内部的一个笑话。它还出现在 Google Chrome 任务管理器中。 它没有任何目的,只是一些工程师觉得很有趣。如果您愿意,这本身就是一个目的。

  1. 在 Chrome 中,使用 Shift+Esc 打开任务管理器。
  2. 右键单击以添加“Goats Teleported”列。
  3. 想象一下。

甚至有一个关于 teleported goats太多 的巨大的Chromium bug报告。

chrome

下面这段Chromium 源代码片段是从HN的评论中盗取的。

int TaskManagerModel::GetGoatsTeleported(int index) const {
  int seed = goat_salt_ * (index + 1);
  return (seed >> 16) & 255;
}

55
Windows XP + 最新版 Chrome = 它不在那里,在 Ubuntu 上我看到了它。 - auselen

311

补充 @djechlin 的回答(顺便说一句,很好的回答!),这个函数调用还可以被用作虚拟代码来在IDE中保持断点,当你想要在某个特定迭代或特定递归调用中停止时。例如:

enter image description here

isUserAGoat() 可以替代一个虚拟变量声明,在IDE中显示为警告信息,而在 Eclipse 中特别的情况下,它会堵塞断点标记,使其难以启用/禁用。如果该方法被用作惯例,所有调用都可以在提交阶段之后通过某些脚本进行过滤。

enter image description here

谷歌的员工是重度的 Eclipse 用户(他们提供了几个作为 Eclipse 插件的项目:Android SDK、GAE 等等),所以 @djechlin 的答案和这个补充答案对我来说很有意义。


15
如果你只是为了快速测试而编写“虚拟”的代码,那使用Eclipse的警告有什么问题吗?我认为这实际上很好,因为它可以在你忘记时提醒你。 - Tomasz
25
问题在于,在Eclipse中,警告标记挡住了断点标记,你需要打开断点视图才能禁用或删除它。 - higuaro
4
是的,我有一个解决方案。您可以右键单击警告符号,然后选择“切换断点”。如果启用了以下行/选项,则表示已创建断点。我的观点是,虚拟代码很糟糕,应该发出警告,以便您不会忘记 ;) - Tomasz
10
@Tomasz 这个解决方案的问题在于你需要事先知道断点位置,因此简单的视觉检查无法让你知道警告隐藏了一个断点。但更好的解决方案是使用条件断点,这样你就可以完全忘记虚拟代码(和约定方法),但这些在不同的 IDE 之间有所不同,并且不能在工作站之间自动共享。 - higuaro

164

在每个Android版本中都有一个有趣的命名方法/常量/其他。

我唯一看到的实际用途是在最后通唤的Google I/O比赛中,他们要求参赛者猜测特定版本的用途,以确定是否阅读了每个发布版的API差异报告。比赛还包括编程问题,但通常先有一些可以自动评分的琐事,以便将提交数量减少到较少的合理数量,这样更容易检查。


12
每个 Android 版本中都有一些有趣的命名方法、常量或其他内容。你可以列举一些吗? 可以,以下是一些例子:
  • Cupcake(松饼)
  • Donut(甜甜圈)
  • Eclair(泡芙)
  • Froyo(冰淇淋松饼)
  • Gingerbread(姜饼)
  • Honeycomb(蜂巢)
  • Ice Cream Sandwich(冰淇淋三明治)
  • Jelly Bean(果冻豆)
  • KitKat(KitKat 巧克力棒)
  • Lollipop(棒棒糖)
  • Marshmallow(棉花糖)
  • Nougat(牛轧糖)
  • Oreo(奥利奥饼干)
  • Pie(派)
  • Android 10 - Q (脆皮甜饼)
  • Android 11 - R (红绸缎)
  • Android 12 - S (雪糕三明治)
- Angelo.Hannes
50
例如,有一种被称为Log.wtf的日志级别,它们称之为What a Terrible Failure。 - Aracem
8
有点像Delphi中的EProgrammerNotFound异常?https://dev59.com/zHI95IYBdhLWcg3w8iv1 - Gerry Coll
12
HoneyComb是AdapterViewAnimator#fyiWillBeAdvancedByHostKThx()。 - Lance Nanek
19
@Angelo.Hannes, 在重力传感器常量中有一个用于“死星”(星球大战)的常量。 - st0le
显示剩余2条评论

158
在语音识别领域,用户被分为“山羊”和“绵羊”。例如,在第89页这里:
“绵羊”是指语音识别非常有效的人,“山羊”是指其效果非常差的人。只有语音识别器知道他们之间的区别。人们无法预测谁的声音会容易被识别,谁的声音不会。最好的方法是设计界面以便能够处理各种环境下各种类型的声音。
也许将来计划标记Android用户为“山羊”,以便为“山羊”的需求配置语音识别引擎。;-)

143

自 API 21(即 Android 5.0/Lollipop SDK 的第一个版本)起,此代码可以检测Goat Simulator 应用是否已安装:

/**
 * Used to determine whether the user making this call is subject to
 * teleportations.
 *
 * <p>As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this method can
 * now automatically identify goats using advanced goat recognition technology.</p>
 *
 * @return Returns true if the user making this call is a goat.
 */
public boolean isUserAGoat() {
    return mContext.getPackageManager()
            .isPackageAvailable("com.coffeestainstudios.goatsimulator");
}

这应该可以清楚地表明,djechlin的建议将其用作无警告的if (false)是一种潜在的灾难性策略。现在对于每个设备以前返回false的东西现在返回了一个看似随机的值:如果这被深深地埋在你的代码中,可能需要很长时间才能弄清楚你的新错误来自哪里。

底线:如果你不能控制方法的实现并决定将其用于API文档中未说明的其他目的,那么你会遇到问题。


23
为什么会有人在生产环境中使用任何形式的 if(false) 呢?得了吧,如果你的代码看起来像这样,那么实现更改只是你面临问题中最不重要的一个。 - djechlin
2
@djechlin "我们需要这个功能吗?更改为if(false)测试功能不需要。提交更改。" - user253751

135

谷歌非常喜欢山羊和基于山羊的彩蛋。甚至有之前在Stack Overflow上发布的帖子提到过这一点。

正如之前的帖子中提到的那样,它也存在于Chrome任务管理器中(它最早出现在2009年):

<message name="IDS_TASK_MANAGER_GOATS_TELEPORTED_COLUMN" desc="The goats teleported column">
    Goats Teleported
</message>

然后在Windows、Linux和Mac版本的Chrome早期2010年)。"传送山羊"的数量实际上是随机

 int TaskManagerModel::GetGoatsTeleported(int index) const {
     int seed = goat_salt_ * (index + 1);
     return (seed >> 16) & 255;
 }

谷歌对山羊的其他参考资料包括:

据我所知,最早将山羊和谷歌联系起来的是原始的“与山羊一起修剪草坪”博客文章。

我们可以安全地假设这只是一个复活节彩蛋,没有实际用途,除了返回false


9
据传IBM在其各种内部软件中也有山羊的参考。 - goat
仅凭用户名就被 @goat 点赞 - rickyduck

116

有一个类似的调用,isUserAMonkey(),如果正在使用MonkeyRunner 工具,则返回true。SDK的解释和这个一样奇怪。

public static boolean isUserAMonkey(){}     

如果用户界面当前被猴子搞乱,则返回true

这里是来源。

我认为这是为了预测一个名字中带有“山羊”的新SDK工具的到来,并且实际上将对该工具的存在进行功能测试。

另请参阅类似的问题,ActivityManager中的奇怪函数:isUserAMonkey。这是什么意思,有什么用?


4
我的假设是这个方法允许ActivityManager报告它是否被monkey UI压力测试工具调用,但我从未确认过。 - CtrlF

49

有趣的复活节彩蛋。
在Chrome的Ubuntu版本中,在任务管理器(shift+esc)中,用右键单击可以添加一个科幻栏目,它在意大利版中被称为“Capre Teletrasportate”(瞬间传送的山羊)。

关于它的一个有趣理论在这里


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