Feat(Tis): DeviceInfo and Build applicationId

Send Device name and AndroidId in DeviceInfo,
Handle multiple release version with different version number and application Id for each psp
This commit is contained in:
Amir Mousavi
2026-05-09 20:30:14 +03:30
parent d73df5524e
commit fe17187df2
16 changed files with 110 additions and 73 deletions
@@ -0,0 +1,24 @@
package com.example.core
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.provider.Settings
fun getDeviceName(): String {
val manufacturer = Build.MANUFACTURER
val model = Build.MODEL
return if (model.startsWith(manufacturer, ignoreCase = true)) {
model
} else {
"$manufacturer $model"
}
}
@SuppressLint("HardwareIds")
fun getAndroidId(context: Context): String {
return Settings
.Secure
.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
}
@@ -1,9 +0,0 @@
package com.example.core.data
import com.example.core.domain.AppConfig
class AppConfigImpl : AppConfig{
override fun androidId(id: String): String {
return "window.WebV.onUUID($id);"
}
}
@@ -1,8 +1,6 @@
package com.example.core.di
import com.example.core.data.AppConfigImpl
import com.example.core.data.PaymentResultImpl
import com.example.core.domain.AppConfig
import com.example.core.domain.PaymentResult
import com.google.gson.Gson
import dagger.Module
@@ -25,9 +23,4 @@ class CoreModule {
): PaymentResult = PaymentResultImpl(
gson = gson
)
@Provides
fun provideAppConfig(
gson: Gson
): AppConfig = AppConfigImpl()
}
@@ -1,7 +0,0 @@
package com.example.core.domain
import com.example.core.model.PaymentResultEntity
interface AppConfig {
fun androidId(id : String) : String
}
@@ -0,0 +1,6 @@
package com.example.core.model
data class DeviceInfo(
val androidId: String,
val deviceName: String
)
@@ -3,8 +3,6 @@ package com.example.design_system
import android.annotation.SuppressLint
import android.app.Activity
import android.view.ViewGroup
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
@@ -36,7 +34,7 @@ fun PspWebView(
modifier: Modifier = Modifier,
onWebView: (WebView) -> Unit,
onPayClick: (amount: Long, id: String?) -> Unit,
onUUID: () -> Unit,
onDeviceInfo: () -> String,
onPrintClick: (printEntities: List<PrintEntity>) -> Unit,
) {
@@ -49,13 +47,13 @@ fun PspWebView(
// Use rememberUpdatedState to ensure the bridge always calls the latest callbacks
val currentOnPayClick by rememberUpdatedState(onPayClick)
val currentOnPrintClick by rememberUpdatedState(onPrintClick)
val currentOnUUID by rememberUpdatedState(onUUID)
val currentOnDeviceInfo by rememberUpdatedState(onDeviceInfo)
val bridge = remember {
PspJavaScriptInterface(
onPayClick = { amount, id -> currentOnPayClick(amount, id) },
onPrintClick = { entities -> currentOnPrintClick(entities) },
onUUID = { currentOnUUID() }
onDeviceInfo = { currentOnDeviceInfo() }
)
}
@@ -11,7 +11,7 @@ import com.google.gson.reflect.TypeToken
class PspJavaScriptInterface(
private val onPayClick: (Long, String?) -> Unit,
private val onPrintClick: (List<PrintEntity>) -> Unit,
private val onUUID: () -> Unit,
private val onDeviceInfo: () -> String,
) {
@JavascriptInterface
@@ -40,12 +40,13 @@ class PspJavaScriptInterface(
@JavascriptInterface
@Keep
fun uuid() {
fun deviceInfo(): String {
Log.d("PspBridge", "uuid called")
try {
onUUID()
return try {
onDeviceInfo()
} catch (e: Exception) {
Log.e("PspBridge", "Error in uuid callback", e)
""
}
}
}
@@ -1,15 +1,12 @@
package com.example.ps4
import android.content.Context
import androidx.annotation.DrawableRes
import com.example.core.domain.Printer
import com.example.core.model.PrintEntity
import javax.inject.Inject
class P4Printer @Inject constructor(
private val context: Context,
) : Printer {
class P4Printer @Inject constructor() : Printer {
override fun print(
+18 -4
View File
@@ -2,10 +2,12 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.ksp)
alias(libs.plugins.hilt)}
alias(libs.plugins.hilt)
}
android {
namespace = "com.example.stage_app"
compileSdk {
version = release(36) {
minorApiLevel = 1
@@ -16,22 +18,33 @@ android {
applicationId = "com.example.stage_app"
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
flavorDimensions.add("module")
productFlavors {
create("p3") {
versionCode = 1
versionName = "1.0"
dimension = "module"
applicationId = "com.example.stage_app_p3"
manifestPlaceholders["appName"] = "TisP3"
}
create("ps4") {
versionCode = 1
versionName = "2.0"
dimension = "module"
applicationId = "com.example.stage_app_p4"
manifestPlaceholders["appName"] = "TisP4"
}
create("standard") {
versionCode = 1
versionName = "1.0"
dimension = "module"
applicationId = "com.example.stage_app"
manifestPlaceholders["appName"] = "Tis"
}
}
@@ -74,6 +87,7 @@ dependencies {
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.retrofit.converter.gson)
implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
testImplementation(libs.junit)
androidTestImplementation(platform(libs.androidx.compose.bom))
+1 -1
View File
@@ -20,7 +20,7 @@
android:name=".PspApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:label="${appName}"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PSP"
@@ -1,6 +1,5 @@
package com.example.stage_app.screen
import android.provider.Settings
import android.webkit.WebView
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
@@ -13,6 +12,8 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.core.getAndroidId
import com.example.core.getDeviceName
import com.example.design_system.PspWebView
import com.example.stage_app.viewmodel.StageViewModel
@@ -60,13 +61,10 @@ fun StageWebViewScreen(
viewModel.print(printEntities)
},
onUUID = {
val androidId = Settings
.Secure
.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
viewModel.sendAndroidId(
androidId
onDeviceInfo = {
viewModel.deviceInfoJson(
androidId = getAndroidId(context),
getDeviceName()
)
}
)
@@ -3,12 +3,13 @@ package com.example.stage_app.viewmodel
import android.content.Intent
import androidx.activity.result.ActivityResult
import androidx.lifecycle.ViewModel
import com.example.core.domain.AppConfig
import com.example.core.domain.PaymentResult
import com.example.core.domain.Printer
import com.example.core.domain.PspService
import com.example.core.model.DeviceInfo
import com.example.core.model.PaymentResultEntity
import com.example.core.model.PrintEntity
import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@@ -17,7 +18,7 @@ class StageViewModel @Inject constructor(
private val pspService: PspService,
private val paymentResult: PaymentResult,
private val printer: Printer,
private val appConfig: AppConfig
private val gson: Gson
) : ViewModel() {
@@ -66,7 +67,12 @@ class StageViewModel @Inject constructor(
)
}
fun sendAndroidId(id: String) {
appConfig.androidId(id)
fun deviceInfoJson(androidId: String, deviceName: String): String {
return gson.toJson(
DeviceInfo(
androidId = androidId,
deviceName = deviceName
)
)
}
}
@@ -1,8 +1,9 @@
package com.example.tis_sep.di
import com.example.core.PspService
import com.example.ps4.Ps4Service
import com.example.core.domain.Printer
import com.example.core.domain.PspService
import com.example.ps4.P4Printer
import com.example.ps4.Ps4Service
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
+13 -5
View File
@@ -17,23 +17,30 @@ android {
applicationId = "com.example.tis_app"
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
flavorDimensions.add("module")
productFlavors {
create("p3") {
versionCode = 1
versionName = "1.0"
dimension = "module"
applicationId = "com.example.tis_app_p3"
manifestPlaceholders["appName"] = "تیس"
}
create("ps4") {
versionCode = 1
versionName = "1.0"
dimension = "module"
}
applicationId = "com.example.tis_app_p4"
manifestPlaceholders["appName"] = "تیس" }
create("standard") {
versionCode = 1
versionName = "1.0"
dimension = "module"
}
applicationId = "com.example.tis_app"
manifestPlaceholders["appName"] = "تیس" }
}
buildTypes {
@@ -72,6 +79,7 @@ dependencies {
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.core.ktx)
implementation(libs.retrofit.converter.gson)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
testImplementation(libs.junit)
@@ -1,6 +1,5 @@
package com.example.tis_app.screen
import android.provider.Settings
import android.webkit.WebView
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
@@ -13,9 +12,13 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.core.getAndroidId
import com.example.core.getDeviceName
import com.example.design_system.PspWebView
import com.example.tis_app.viewmodel.WebViewModel
private const val tisIp = "194.59.214.243:8090"
@Composable
fun TisWebViewScreen(
modifier: Modifier = Modifier,
@@ -58,13 +61,10 @@ fun TisWebViewScreen(
viewModel.print(printEntities)
},
onUUID = {
val androidId = Settings
.Secure
.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
viewModel.sendAndroidId(
androidId
onDeviceInfo = {
viewModel.deviceInfoJson(
androidId = getAndroidId(context),
getDeviceName()
)
}
)
@@ -3,13 +3,14 @@ package com.example.tis_app.viewmodel
import android.content.Intent
import androidx.activity.result.ActivityResult
import androidx.lifecycle.ViewModel
import com.example.core.domain.AppConfig
import com.example.core.domain.PaymentResult
import com.example.core.domain.Printer
import com.example.core.domain.PspService
import com.example.core.model.DeviceInfo
import com.example.core.model.PaymentResultEntity
import com.example.core.model.PrintEntity
import com.example.tis_app.R
import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@@ -18,7 +19,7 @@ class WebViewModel @Inject constructor(
private val pspService: PspService,
private val paymentResult: PaymentResult,
private val printer: Printer,
private val appConfig: AppConfig
private val gson: Gson
) : ViewModel() {
@@ -37,14 +38,20 @@ class WebViewModel @Inject constructor(
activityResult = activityResult
)
}
fun print(printEntities : List<PrintEntity>) {
fun print(printEntities: List<PrintEntity>) {
printer.print(
printEntities = printEntities,
icon = R.drawable.tis_icon
)
}
fun sendAndroidId(id : String) {
appConfig.androidId(id)
fun deviceInfoJson(androidId: String, deviceName: String): String {
return gson.toJson(
DeviceInfo(
androidId = androidId,
deviceName = deviceName
)
)
}
}