diff --git a/hockeysdk/src/main/java/net/hockeyapp/android/UpdateManager.java b/hockeysdk/src/main/java/net/hockeyapp/android/UpdateManager.java index 3cfa49575..33a7fa5ae 100644 --- a/hockeysdk/src/main/java/net/hockeyapp/android/UpdateManager.java +++ b/hockeysdk/src/main/java/net/hockeyapp/android/UpdateManager.java @@ -212,22 +212,26 @@ private static boolean checkExpiryDateForBackground(UpdateManagerListener listen /** * Returns true if the build was installed through a market. */ - public static boolean installedFromMarket(WeakReference weakContext) { + protected static boolean installedFromMarket(WeakReference weakContext) { boolean result = false; Context context = weakContext.get(); if (context != null) { try { String installer = context.getPackageManager().getInstallerPackageName(context.getPackageName()); - - // if installer string is null or empty, it's installed via ADB + // if installer string is not null it might be installed by market if (!TextUtils.isEmpty(installer)) { - // on some devices (Xiaomi) the installer identifier will be "adb", which is not to be considered as a market installation - result = !TextUtils.equals(installer, INSTALLER_ADB); + result = true; + // on Android Nougat and up when installing an app through the package installer (which HockeyApp uses itself), the installer will be // "com.google.android.packageinstaller" which is also not to be considered as a market installation - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - result = !TextUtils.equals(installer, INSTALLER_PACKAGE_INSTALLER_NOUGAT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && TextUtils.equals(installer, INSTALLER_PACKAGE_INSTALLER_NOUGAT)) { + result = false; + } + + // on some devices (Xiaomi) the installer identifier will be "adb", which is not to be considered as a market installation + if (TextUtils.equals(installer, INSTALLER_ADB)) { + result = false; } } diff --git a/hockeysdk/src/test/java/net/hockeyapp/android/UpdateManagerTest.java b/hockeysdk/src/test/java/net/hockeyapp/android/UpdateManagerTest.java index 82f73f7fd..a71705523 100644 --- a/hockeysdk/src/test/java/net/hockeyapp/android/UpdateManagerTest.java +++ b/hockeysdk/src/test/java/net/hockeyapp/android/UpdateManagerTest.java @@ -35,6 +35,9 @@ public class UpdateManagerTest { @Before public void setUp() throws NoSuchFieldException, IllegalAccessException { + // Reset Build version code + Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.BASE); + mockContext = mock(Context.class); mockPackageManager = mock(PackageManager.class); @@ -56,42 +59,57 @@ public Boolean answer(InvocationOnMock invocation) throws Throwable { } }); - when(mockContext.getPackageManager()).thenReturn(mockPackageManager); contextWeakReference = new WeakReference<>(mockContext); } - @Test public void testInstalledViaADBDefault() { when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn(null); + // Typically, the installer string for ADB is null assertFalse(UpdateManager.installedFromMarket(contextWeakReference)); + // or an empty string when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn(""); + assertFalse(UpdateManager.installedFromMarket(contextWeakReference)); + // Verify this also works on Android Nougat + Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N); assertFalse(UpdateManager.installedFromMarket(contextWeakReference)); } @Test public void testInstalledViaGooglePlay() { + // Set typical identifier for Google Play and check when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("com.google.play"); assertTrue(UpdateManager.installedFromMarket(contextWeakReference)); + + Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N); + assertTrue(UpdateManager.installedFromMarket(contextWeakReference)); } @Test public void testInstalledViaADBXiaomi() { + // On some devices, e.g. Xiaomi devices, launching via USB will return "adb" for the installer when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("adb"); assertFalse(UpdateManager.installedFromMarket(contextWeakReference)); + + Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N); + assertFalse(UpdateManager.installedFromMarket(contextWeakReference)); } @Test public void testInstalledViaPackageManagerNougat() { + // On Android Nougat, installing packages using HockeyApp (using the package manager) will list the following installer identifier when(mockPackageManager.getInstallerPackageName(any(String.class))).thenReturn("com.google.android.packageinstaller"); + // When not on Android Nougat this is considered "store" assertTrue(UpdateManager.installedFromMarket(contextWeakReference)); + + // Test desired behavior on Android Nougat Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.N); assertFalse(UpdateManager.installedFromMarket(contextWeakReference)); }