Skip to content

Commit

Permalink
Addded build variant to test Google Play Store compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
Ixam97 committed Mar 30, 2024
1 parent 5de0b14 commit fac5ede
Show file tree
Hide file tree
Showing 14 changed files with 389 additions and 58 deletions.
20 changes: 17 additions & 3 deletions automotive/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ android {
defaultConfig {
minSdkVersion 29
targetSdkVersion 33
versionCode 202
versionName "0.26.0.0010"
versionCode 205
versionName "0.27.0.0001"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
flavorDimensions "version"
// flavorDimensions "version"
// flavorDimensions "aaos"
flavorDimensions("version", "aaos")

productFlavors {
stable {
Expand All @@ -27,6 +29,15 @@ android {
dimension "version"
applicationId "com.ixam97.carStatsViewer_dev"
}

regular {
dimension "aaos"
}

play {
dimension "aaos"
applicationIdSuffix "play"
}
}

buildTypes {
Expand Down Expand Up @@ -88,6 +99,9 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.github.matthiaszimmermann:EGM96:master-SNAPSHOT'

implementation "androidx.car.app:app:1.3.0-rc01"
implementation "androidx.car.app:app-automotive:1.3.0-rc01"

implementation("androidx.room:room-ktx:2.5.0")
kapt("androidx.room:room-compiler:2.5.0")

Expand Down
5 changes: 5 additions & 0 deletions automotive/src/devPlay/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">Car Stats Viewer (Play Edition, Dev)</string>
<string name="app_name_short" translatable="false">CSV (Play, Dev)</string>
</resources>
55 changes: 0 additions & 55 deletions automotive/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,59 +24,4 @@
android:name="android.hardware.type.automotive"
android:required="true"/>

<application
android:name=".CarStatsViewer"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:hasFragileUserData="true"
android:theme="@style/AppTheme">
<receiver android:name=".AutoStartReceiver"
android:exported="true"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
<intent-filter>
<action android:name="com.ixam97.carStatsViewer.RestartAction" />
</intent-filter>
</receiver>

<activity android:name=".ui.activities.PermissionsActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="distractionOptimized" android:value="true"/>
</activity>
<activity android:name=".ui.activities.MainActivity"
android:exported="false">
<meta-data android:name="distractionOptimized" android:value="true"/>
</activity>
<activity android:name=".ui.activities.SettingsActivity"
android:exported="false">
<meta-data android:name="distractionOptimized" android:value="true"/>
</activity>
<activity android:name=".ui.activities.HistoryActivity" android:exported="false" />
<activity android:name=".ui.activities.SettingsMainViewActivity" android:exported="false"/>
<activity android:name=".ui.activities.SettingsVehicleActivity" android:exported="false"/>
<activity android:name=".ui.activities.LibsActivity" android:exported="false" />
<activity android:name=".ui.activities.AboutActivity" android:exported="false" />
<activity android:name=".ui.activities.SettingsApisActivity" android:exported="false" />
<activity android:name=".ui.activities.DebugActivity"
android:exported="false">
<meta-data android:name="distractionOptimized" android:value="true"/>
</activity>
<service android:name=".dataCollector.DataCollector"
android:foregroundServiceType="location"
android:enabled="true"
android:exported="true"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.ixam97.carStatsViewer.aaos

import android.content.Intent
import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.model.Action
import androidx.car.app.model.ActionStrip
import androidx.car.app.model.CarColor
import androidx.car.app.model.CarIcon
import androidx.car.app.model.ItemList
import androidx.car.app.model.ListTemplate
import androidx.car.app.model.Row
import androidx.car.app.model.SectionedItemList
import androidx.car.app.model.Template
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.IconCompat
import com.ixam97.carStatsViewer.CarStatsViewer
import com.ixam97.carStatsViewer.R
import com.ixam97.carStatsViewer.ui.activities.HistoryActivity
import com.ixam97.carStatsViewer.ui.activities.MainActivity
import com.ixam97.carStatsViewer.ui.activities.SettingsActivity
import com.ixam97.carStatsViewer.utils.InAppLogger
import com.ixam97.carStatsViewer.utils.StringFormatters


class CarStatsViewerScreen(carContext: CarContext) : Screen(carContext) {

private var apiStateString = "No Data"
private var speed : Float? = 0f
private var power : Float? = 0f
init {
setupListeners()
}

private fun setupListeners() {
val exec = ContextCompat.getMainExecutor(carContext)
CarStatsViewer.watchdog.setAaosCallback(exec) { updateLiveData() }
CarStatsViewer.dataProcessor.setAaosCallback(exec) { updateLiveData() }
}
private fun updateLiveData() {
val apiState = CarStatsViewer.watchdog.getCurrentWatchdogState().apiState
val realTimeData = CarStatsViewer.dataProcessor.realTimeData
InAppLogger.d("[AAOS] Updating live data: $apiState")
apiStateString = apiState.toString()
speed = realTimeData.speed
power = realTimeData.power
invalidate()
}
override fun onGetTemplate(): Template {
val settingsActivityIntent = Intent(carContext, SettingsActivity::class.java)
settingsActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val mainActivityIntent = Intent(carContext, MainActivity::class.java)
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val historyActivityIntent = Intent(carContext, HistoryActivity::class.java)
historyActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

val dashboardRow = Row.Builder()
.setTitle("Open Dashboard")
.setOnClickListener {
carContext.startActivity(mainActivityIntent)
}
.setImage(
CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_diagram))
.setTint(CarColor.DEFAULT).build()
)
.setBrowsable(true)
.build()
val historyRow = Row.Builder()
.setTitle("Open Trip History")
.setOnClickListener {
carContext.startActivity(historyActivityIntent)
}
.setImage(
CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_history))
.setTint(CarColor.DEFAULT).build()
)
.setBrowsable(true)
.build()

return ListTemplate.Builder().apply {
setTitle(carContext.getString(R.string.app_name))
setHeaderAction(Action.APP_ICON)
setActionStrip(ActionStrip.Builder().apply {
addAction(Action.Builder().apply {
setIcon(CarIcon.Builder(
IconCompat.createWithResource(carContext, R.drawable.ic_settings)
).setTint(CarColor.DEFAULT).build())
setOnClickListener {
carContext.startActivity(settingsActivityIntent)
}
}.build())
}.build())

addSectionedList(SectionedItemList.create(ItemList.Builder().apply {
addItem(dashboardRow)
addItem(historyRow)
}.build(), "Main Functions"))

addSectionedList(SectionedItemList.create(ItemList.Builder().apply {
addItem(Row.Builder().apply {
setTitle(apiStateString)
}.build())
}.build(), "API Status"))

addSectionedList(SectionedItemList.create(ItemList.Builder().apply {
addItem(Row.Builder().apply {
setTitle("${((speed?:0f) * 3.6f).toInt()} km/h")
addText("Speed")
}.build())
addItem(Row.Builder().apply {
setTitle("${((power?:0f) / 1_000_000).toInt()} kW")
addText("Power")
}.build())
}.build(), "Car Data"))

}.build()
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ixam97.carStatsViewer.aaos

import android.content.pm.ApplicationInfo
import androidx.car.app.CarAppService
import androidx.car.app.Session
import androidx.car.app.SessionInfo
import androidx.car.app.validation.HostValidator


class CarStatsViewerService : CarAppService() {
override fun onCreateSession(sessionInfo: SessionInfo): Session {
return CarStatsViewerSession()
}

override fun createHostValidator(): HostValidator {
return if (getApplicationInfo().flags and ApplicationInfo.FLAG_DEBUGGABLE != 0) {
HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
} else {
HostValidator.Builder(getApplicationContext())
.addAllowedHosts(androidx.car.app.R.array.hosts_allowlist_sample)
.build()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.ixam97.carStatsViewer.aaos

import android.content.Intent
import android.content.pm.PackageManager
import androidx.car.app.Screen
import androidx.car.app.Session
import com.ixam97.carStatsViewer.dataCollector.DataCollector
import com.ixam97.carStatsViewer.ui.activities.PermissionsActivity

class CarStatsViewerSession : Session() {

val permissions = PermissionsActivity.PERMISSIONS.toList()
override fun onCreateScreen(intent: Intent): Screen {
var neededPermissions = permissions.filter { carContext.checkSelfPermission(it) != PackageManager.PERMISSION_GRANTED }
if (neededPermissions.isNotEmpty()) {
carContext.requestPermissions(permissions) {granted,_ ->
if (granted.containsAll(permissions)) {
startService()
}
}
} else {
startService()
}
return CarStatsViewerScreen(carContext)
}

private fun startService() {
carContext.startForegroundService(Intent(carContext, DataCollector::class.java))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.update
import java.util.*
import java.util.concurrent.Executor
import kotlin.math.absoluteValue
import kotlin.math.roundToInt

Expand Down Expand Up @@ -59,6 +60,9 @@ class DataProcessor {

var dataInitialized: Boolean? = null

private var aaosExec : Executor? = null
private var aaosRunnable : java.lang.Runnable? = null

/**
* List of local copies of the current trips. Used for storing sum values and saving them to
* disk less frequently. This should prevent hiccups when adding sums of distance and energy.
Expand Down Expand Up @@ -90,6 +94,7 @@ class DataProcessor {
private set(value) {
field = value
_realTimeDataFlow.value = value
aaosExec?.execute(aaosRunnable)
}

// private var chargingTripData = ChargingTripData()
Expand Down Expand Up @@ -804,6 +809,11 @@ class DataProcessor {
}
}

fun setAaosCallback(exec: Executor, runnable: java.lang.Runnable) {
aaosExec = exec
aaosRunnable = runnable
}

/** Weird stuff for range estimate, not quite working as intended yet. */
/*
fun updateUsedStateOfCharge(usedStateOfChargeDelta: Double) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,16 @@ class MainActivity : FragmentActivity() {
CarStatsViewer.getChangelogDialog(this).show()
appPreferences.versionString = BuildConfig.VERSION_NAME
}

if (BuildConfig.FLAVOR_aaos == "play") {
main_title.visibility = View.GONE
main_title_icon.visibility = View.GONE
main_title_dashboard.visibility = View.VISIBLE
main_button_back.visibility = View.VISIBLE
main_button_back.setOnClickListener {
finish()
}
}
}

override fun onDestroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,32 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.util.concurrent.Executor

class Watchdog() {
private val _watchdogStateFlow = MutableStateFlow<WatchdogState>(WatchdogState())
val watchdogStateFlow = _watchdogStateFlow.asStateFlow()
private val _watchdogTriggerFlow = MutableSharedFlow<Unit>(replay = 0)
val watchdogTriggerFlow = _watchdogTriggerFlow.asSharedFlow()

private var executor :Executor? = null
private var runnable :Runnable? = null

fun getCurrentWatchdogState() = watchdogStateFlow.value

fun setAaosCallback(executor: Executor, runnable: Runnable) {
this.executor = executor
this.runnable = runnable
}

fun updateWatchdogState(watchdogState: WatchdogState) {
_watchdogStateFlow.value = watchdogState
}

fun triggerWatchdog() {
CoroutineScope(Dispatchers.Default).launch {
_watchdogTriggerFlow.emit(Unit)
executor?.execute(runnable)
}
}
}
11 changes: 11 additions & 0 deletions automotive/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@
style="@style/title_text_style"
android:text="@string/app_name"/>

<ImageButton
android:visibility="gone"
android:id="@+id/main_button_back"
style="@style/title_back_button_style" />

<TextView
android:visibility="gone"
android:id="@+id/main_title_dashboard"
style="@style/title_text_style"
android:text="Dashboard"/>

<ImageView
android:id="@+id/main_icon_location_status"
android:layout_width="wrap_content"
Expand Down
Loading

0 comments on commit fac5ede

Please sign in to comment.