chore: add mobile app

This commit is contained in:
2026-02-07 22:33:02 +01:00
parent db34640acc
commit e89384ad4e
29327 changed files with 3886944 additions and 12 deletions
+27
View File
@@ -0,0 +1,27 @@
plugins {
id 'com.android.library'
id 'expo-module-gradle-plugin'
}
apply from: "../scripts/get-app-config-android.gradle"
group = 'host.exp.exponent'
version = '18.0.13'
expoModule {
// We can't prebuild the module because we need to apply `get-app-config-android.gradle` script.
canBePublished false
}
android {
namespace "expo.modules.constants"
defaultConfig {
versionCode 33
versionName "18.0.13"
}
}
dependencies {
api "androidx.annotation:annotation:1.0.0"
implementation "commons-io:commons-io:2.6"
}
@@ -0,0 +1,3 @@
<manifest>
</manifest>
@@ -0,0 +1,20 @@
// Copyright 2015-present 650 Industries. All rights reserved.
package expo.modules.constants
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class ConstantsModule : Module() {
override fun definition() = ModuleDefinition {
Name("ExponentConstants")
Constants {
return@Constants appContext.constants?.constants ?: emptyMap()
}
AsyncFunction<String?>("getWebViewUserAgentAsync") {
return@AsyncFunction System.getProperty("http.agent")
}
}
}
@@ -0,0 +1,11 @@
package expo.modules.constants
import android.content.Context
import expo.modules.core.BasePackage
import expo.modules.core.interfaces.InternalModule
class ConstantsPackage : BasePackage() {
override fun createInternalModules(context: Context): List<InternalModule> =
listOf(ConstantsService(context))
}
@@ -0,0 +1,96 @@
package expo.modules.constants
import org.apache.commons.io.IOUtils
import expo.modules.core.interfaces.InternalModule
import expo.modules.interfaces.constants.ConstantsInterface
import android.os.Build
import android.util.Log
import android.content.Context
import java.io.FileNotFoundException
import java.lang.Exception
import java.nio.charset.StandardCharsets
import java.util.*
private val TAG = ConstantsService::class.java.simpleName
private const val CONFIG_FILE_NAME = "app.config"
open class ConstantsService(private val context: Context) : InternalModule, ConstantsInterface {
var statusBarHeightInternal = context.resources.getIdentifier("status_bar_height", "dimen", "android")
.takeIf { it > 0 }
?.let { (context.resources::getDimensionPixelSize)(it) }
?.let { pixels -> convertPixelsToDp(pixels.toFloat(), context) }
?: 0
private val sessionId = UUID.randomUUID().toString()
enum class ExecutionEnvironment(val string: String) {
BARE("bare"),
STANDALONE("standalone"),
STORE_CLIENT("storeClient")
}
override fun getExportedInterfaces(): List<Class<*>> = listOf(ConstantsInterface::class.java)
override fun getConstants(): Map<String, Any?> {
return mutableMapOf(
"sessionId" to sessionId,
"executionEnvironment" to ExecutionEnvironment.BARE.string,
"statusBarHeight" to statusBarHeightInternal,
"deviceName" to deviceName,
"systemFonts" to systemFonts,
"systemVersion" to systemVersion,
"manifest" to appConfig,
"platform" to mapOf<String, Map<String, Any>>("android" to emptyMap())
)
}
// Just use package name in vanilla React Native apps.
override fun getAppScopeKey(): String? = context.packageName
override fun getDeviceName(): String = Build.MODEL
override fun getStatusBarHeight() = statusBarHeightInternal
override fun getSystemVersion(): String = Build.VERSION.RELEASE
// From https://github.com/dabit3/react-native-fonts
override fun getSystemFonts() = listOf(
"normal",
"notoserif",
"sans-serif",
"sans-serif-light",
"sans-serif-thin",
"sans-serif-condensed",
"sans-serif-medium",
"serif",
"Roboto",
"monospace"
)
private val appConfig: String?
get() {
try {
context.assets.open(CONFIG_FILE_NAME).use {
stream ->
return IOUtils.toString(stream, StandardCharsets.UTF_8)
}
} catch (e: FileNotFoundException) {
// do nothing, expected in managed apps
} catch (e: Exception) {
Log.e(TAG, "Error reading embedded app config", e)
}
return null
}
companion object {
private fun convertPixelsToDp(px: Float, context: Context): Int {
val resources = context.resources
val metrics = resources.displayMetrics
val dp = px / (metrics.densityDpi / 160f)
return dp.toInt()
}
}
}