Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ interface IDeviceService {
val hasAllHMSLibrariesForPushKit: Boolean
val hasFCMLibrary: Boolean
val jetpackLibraryStatus: JetpackLibraryStatus
val supportsHMS: Boolean

fun supportsGooglePush(): Boolean

enum class JetpackLibraryStatus {
MISSING,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.onesignal.core.internal.device.impl

import android.content.Context
import android.content.pm.PackageManager
import com.onesignal.common.AndroidUtils
import com.onesignal.core.internal.application.IApplicationService
Expand All @@ -10,6 +11,7 @@ internal class DeviceService(private val _applicationService: IApplicationServic
companion object {
private const val HMS_CORE_SERVICES_PACKAGE = "com.huawei.hwid" // = HuaweiApiAvailability.SERVICES_PACKAGE
private const val GOOGLE_PLAY_SERVICES_PACKAGE = "com.google.android.gms" // = GoogleApiAvailability.GOOGLE_PLAY_SERVICES_PACKAGE
private const val PREFER_HMS_METADATA_NAME = "com.onesignal.preferHMS"
private const val HMS_AVAILABLE_SUCCESSFUL = 0
}

Expand Down Expand Up @@ -37,7 +39,17 @@ internal class DeviceService(private val _applicationService: IApplicationServic
override val deviceType: IDeviceService.DeviceType
get() {
if (supportsADM()) return IDeviceService.DeviceType.Fire
if (supportsGooglePush()) return IDeviceService.DeviceType.Android

val supportsHMS = supportsHMS
val supportsFCM = supportsGooglePush()

if (supportsFCM && supportsHMS) {
val context = _applicationService.appContext
val preferHMS = AndroidUtils.getManifestMetaBoolean(context, PREFER_HMS_METADATA_NAME)
return if (preferHMS) IDeviceService.DeviceType.Huawei else IDeviceService.DeviceType.Android
}

if (supportsFCM) return IDeviceService.DeviceType.Android

// Some Huawei devices have both FCM & HMS support, but prefer FCM (Google push) over HMS
if (supportsHMS) return IDeviceService.DeviceType.Huawei
Expand All @@ -62,7 +74,7 @@ internal class DeviceService(private val _applicationService: IApplicationServic
return IDeviceService.JetpackLibraryStatus.OK
}

private fun supportsGooglePush(): Boolean {
override fun supportsGooglePush(): Boolean {
// 1. If app does not have the FCM library it won't support Google push
return if (!hasFCMLibrary) false else isGMSInstalledAndEnabled

Expand Down Expand Up @@ -104,7 +116,7 @@ internal class DeviceService(private val _applicationService: IApplicationServic
}
}

private val supportsHMS: Boolean
override val supportsHMS: Boolean
get() {
// 1. App should have the HMSAvailability for best detection and must have PushKit libraries
return if (!hasHMSAvailabilityLibrary() || !hasAllHMSLibrariesForPushKit) false else isHMSCoreInstalledAndEnabled()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.onesignal.core.internal.device

import androidx.test.core.app.ApplicationProvider
import br.com.colman.kotest.android.extensions.robolectric.RobolectricTest
import com.onesignal.common.AndroidUtils
import com.onesignal.core.internal.device.impl.DeviceService
import com.onesignal.mocks.MockHelper
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockkObject
import io.mockk.spyk

@RobolectricTest
class DeviceServiceTests : FunSpec({
test("devicetype is Huawei when preferHMS manifest value is true when a device supports HMS and FCM") {
// Given
val mockDeviceService = Mocks().deviceService
every { mockDeviceService.supportsHMS } returns true
every { mockDeviceService.supportsGooglePush() } returns true
mockkObject(AndroidUtils)
every { AndroidUtils.getManifestMetaBoolean(ApplicationProvider.getApplicationContext(), "com.onesignal.preferHMS") } returns true

// When
val deviceType = mockDeviceService.deviceType

// Then
deviceType shouldBe IDeviceService.DeviceType.Huawei
}

test("devicetype is FCM when preferHMS manifest value is false when a device supports HMS and FCM") {
// Given
val mockDeviceService = Mocks().deviceService
every { mockDeviceService.supportsHMS } returns true
every { mockDeviceService.supportsGooglePush() } returns true
mockkObject(AndroidUtils)
every { AndroidUtils.getManifestMetaBoolean(ApplicationProvider.getApplicationContext(), "com.onesignal.preferHMS") } returns false

// When
val deviceType = mockDeviceService.deviceType

// Then
deviceType shouldBe IDeviceService.DeviceType.Android
}

test("devicetype is FCM when preferHMS manifest value is missing when a device supports HMS and FCM") {
// Given
val mockDeviceService = Mocks().deviceService
every { mockDeviceService.supportsHMS } returns true
every { mockDeviceService.supportsGooglePush() } returns true

// When
val deviceType = mockDeviceService.deviceType

// Then
deviceType shouldBe IDeviceService.DeviceType.Android
}
})

private class Mocks {
val applicationService =
run {
val mockApplicationService = MockHelper.applicationService()
every { mockApplicationService.appContext } returns ApplicationProvider.getApplicationContext()
mockApplicationService
}

val deviceService: DeviceService by lazy {
spyk(
DeviceService(
applicationService,
),
)
}
}