可以在代码中区分APK是通过Play Store安装还是手动安装吗?

4

可能重复问题:
如何知道应用程序是从Google Play还是侧载安装的?

我们有一个可以在多个移动平台之间移植的应用程序。它提供了自己的更新机制,以获取应用程序使用的相当大的数据。现在,这个机制也可以下载应用程序的更新版本。如果用户手动安装了.apk文件,我们希望通过该机制向他们发送新版本,但如果他们是从Android市场(或任何其他市场)安装的,则市场应用程序将负责升级,并且我们自己做这件事会与市场应用程序冲突。

那么,是否可以从应用程序内部检测应用程序是通过市场安装的还是其他方式安装的?


我相信这是不可能完成的。 - Tobrun
2
你肯定不能区分非Play商店市场和“手动”安装,因为所有非Play商店市场都涉及手动安装。 - CommonsWare
1个回答

7
当您从Google Play安装时,您将在安装过程中收到一个com.android.vending.INSTALL_REFERRER广播。只需创建广播接收器,并在您的SharedPreferences中设置一个布尔值,例如fromGooglePlay,您可以在接收器中将其设置为true。
然而,我认为您不能针对其他应用商店(如亚马逊)拥有类似的接收器。 编辑1: 正如@zapl在评论中指出的那样,这在Android 3.0及以上版本上不起作用,因为尚未启动至少一次的应用程序无法接收广播等。
但是,您可以尝试另一种解决方案:
在您的应用程序中,有一个常量布尔值,例如GOOGLE_PLAY_BUILD。在为Google Play构建apk时,将其设置为true,并在为手动分发构建apk时将其设置为false。然后在运行时简单地检查其值,并相应地采取行动。 编辑2: 为了解决您对于Root设备分发应用的担忧,这里提供一个更详细的系统。每个设备都有一个唯一的ANDROID_ID(尽管4.2上的多用户会有多个ID,与文档所说不同)。实质上,您只需要一个唯一的设备ID,因此即使是MAC地址也可以。在Web服务器上创建一个表格来存储唯一ID、是否接收到Google Play广播以及Google Play标志的值。当应用程序首次启动时,将这些详细信息添加到该设备的表中。之后再次启动应用程序时,只需检查所有三个详细信息是否与本地存储的副本匹配。如果用户从Root用户那里获取应用程序并安装它,则Google Play标志似乎匹配,但安装引荐部分不匹配。遗憾的是,这只适用于蜂窝前的设备。或者在稍微信任的系统中,您可以简单地询问用户他们是手动安装还是从Google Play安装的。如果您提到这是选择更新方法而不是起诉他们未从Google Play安装,我相信他们会愿意说出真相。
正如 @Jan 在评论中指出的那样,PackageManager 中似乎有一个 getInstallerPackageName() 方法可用于此目的。

你的第二个解决方案是我最初想到的,但如果你想查看是否有root用户分发了apk呢..你会得到Google Play的真实结果,但它们是手动完成的。 - Jimmar
好的,你可以进行更详细的检查,但是你需要拥有一个Web服务器。我会在答案中添加这个详细的内容。 - Raghav Sood
谢谢,我们可能会选择使用构建标志,因为它非常容易,特别是考虑到我们已经有了那么多的标志以及支持该系统的复杂结构。 - Jan Hudec
1
@JanHudec 这里有一个链接:http://android-developers.blogspot.de/2010/09/securing-android-lvl-applications.html,但它并不是真正的安全措施。这个链接也许更有用:http://stackoverflow.com/questions/12981397/how-to-secure-android-application-from-app-lucky-pathcer。 - zapl
我刚刚发现了另一个类似的问题,有更正确的答案(在上面标记为重复)。 - Jan Hudec
显示剩余3条评论

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