Skip to content

Commit

Permalink
chore: set device_type accordingly to Mobile, TV, or Tablet
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto committed Feb 8, 2024
1 parent c8fccd9 commit 0709375
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Next

- set `device_type` accordindly, Mobile, TV, Tablet ([#91](https://github.com/PostHog/posthog-android/pull/91))

## 3.1.6 - 2024-02-01

- recording: clone drawable before using ([#91](https://github.com/PostHog/posthog-android/pull/91))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package com.posthog.android.internal

import android.Manifest
import android.annotation.SuppressLint
import android.app.UiModeManager
import android.content.Context
import android.content.res.Configuration
import android.net.ConnectivityManager
import android.os.Build
import android.util.DisplayMetrics
import com.posthog.android.PostHogAndroidConfig
import com.posthog.internal.PostHogContext
import java.util.Locale
import java.util.TimeZone
import kotlin.math.pow
import kotlin.math.sqrt

/**
* Reads the static and dynamic context
Expand Down Expand Up @@ -41,10 +46,12 @@ internal class PostHogAndroidContext(
staticContext["\$app_name"] = context.applicationInfo.loadLabel(context.packageManager)

staticContext["\$device_manufacturer"] = Build.MANUFACTURER
staticContext["\$device_model"] = Build.MODEL
staticContext["\$device_name"] = Build.DEVICE
staticContext["\$device_model"] = Build.MODEL // returns Pixel 7a
staticContext["\$device_name"] = Build.DEVICE // returns lynx
// Check https://github.com/PostHog/posthog-flutter/issues/49 and change if needed
staticContext["\$device_type"] = "Mobile"
getDeviceType(context)?.let {
staticContext["\$device_type"] = it
}
staticContext["\$os_name"] = "Android"
staticContext["\$os_version"] = Build.VERSION.RELEASE

Expand All @@ -54,6 +61,77 @@ internal class PostHogAndroidContext(
staticContext
}

// Inspired from https://github.com/expo/expo/blob/86bafbaa0b8b9fff5b11f0e5bcf9097bb5ac8878/packages/expo-device/android/src/main/java/expo/modules/device/DeviceModule.kt#L52
// missing auto, watch, embedded, desktop, etc
private fun getDeviceType(context: Context): String? {
// Detect TVs via UI mode (Android TVs) or system features (Fire TV).
if (context.packageManager.hasSystemFeature("amazon.hardware.fire_tv")) {
return "TV"
}

val uiManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager?
uiManager?.let {
if (it.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION) {
return "TV"
}
}

val deviceTypeFromResourceConfiguration = getDeviceTypeFromResourceConfiguration(context)
return deviceTypeFromResourceConfiguration ?: getDeviceTypeFromPhysicalSize(context)
}

@Suppress("DEPRECATION")
private fun getDeviceTypeFromPhysicalSize(context: Context): String? {
// Find the current window manager, if none is found we can't measure the device physical size.
val windowManager = context.windowManager()
?: return null

// Get display metrics to see if we can differentiate phones and tablets.
val widthInches: Double
val heightInches: Double

// windowManager.defaultDisplay was marked as deprecated in API level 30 (Android R) and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowBounds = windowManager.currentWindowMetrics.bounds
val densityDpi = context.resources.configuration.densityDpi
widthInches = windowBounds.width() / densityDpi.toDouble()
heightInches = windowBounds.height() / densityDpi.toDouble()
} else {
val metrics = DisplayMetrics()
windowManager.defaultDisplay.getRealMetrics(metrics)
widthInches = metrics.widthPixels / metrics.xdpi.toDouble()
heightInches = metrics.heightPixels / metrics.ydpi.toDouble()
}

// Calculate physical size.
val diagonalSizeInches = sqrt(widthInches.pow(2.0) + heightInches.pow(2.0))

return if (diagonalSizeInches in 3.0..6.9) {
// Devices in a sane range for phones are considered to be phones.
"Mobile"
} else if (diagonalSizeInches > 6.9 && diagonalSizeInches <= 18.0) {
// Devices larger than a phone and in a sane range for tablets are tablets.
"Tablet"
} else {
// Otherwise, we don't know what device type we're on.
null
}
}

// Device type based on the smallest screen width quantifier
// https://developer.android.com/guide/topics/resources/providing-resources#SmallestScreenWidthQualifier
private fun getDeviceTypeFromResourceConfiguration(context: Context): String? {
val smallestScreenWidthDp = context.resources.configuration.smallestScreenWidthDp

return if (smallestScreenWidthDp == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
null
} else if (smallestScreenWidthDp >= 600) {
"Tablet"
} else {
"Mobile"
}
}

override fun getStaticContext(): Map<String, Any> {
return cacheStaticContext
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal class NextDrawListener(
// the real ViewTreeObserver.
// https://android.googlesource.com/platform/frameworks/base/+/9f8ec54244a5e0343b9748db3329733f259604f3
view.viewTreeObserver?.let { viewTreeObserver ->
if (Build.VERSION.SDK_INT >= 26 || (viewTreeObserver.isAlive && view.isAttachedToWindow)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || (viewTreeObserver.isAlive && view.isAttachedToWindow)) {
viewTreeObserver.addOnDrawListener(this)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class NormalActivity : ComponentActivity() {
// }
// startActivity(Intent(this, NothingActivity::class.java))
// finish()

Thread {
client.newCall(
okhttp3.Request.Builder()
Expand Down

0 comments on commit 0709375

Please sign in to comment.