From eede556a77b508974ff2364997dd083aa6708277 Mon Sep 17 00:00:00 2001 From: Daniel Shokouhi Date: Tue, 4 Jan 2022 16:32:45 -0800 Subject: [PATCH] Initial commit of the Quest build (#2106) * Initial commit of the Quest build * Tweak readme --- .github/actions/inflate-secrets/action.yml | 1 + .github/mock-google-services.json | 26 ++++++++ .github/workflows/beta.yml | 10 +++ .github/workflows/release.yml | 10 +++ README.md | 6 +- app/build.gradle.kts | 8 +++ .../android/launch/LaunchActivity.kt | 2 +- .../android/settings/SettingsFragment.kt | 55 ++++++++-------- app/src/quest/AndroidManifest.xml | 17 +++++ .../companion/android/CrashHandling.kt | 7 ++ .../android/launch/LaunchPresenterImpl.kt | 29 +++++++++ .../android/onboarding/MessagingToken.kt | 5 ++ .../android/sensors/ActivitySensorManager.kt | 32 +++++++++ .../android/sensors/GeocodeSensorManager.kt | 35 ++++++++++ .../android/sensors/LocationSensorManager.kt | 65 +++++++++++++++++++ .../settings/wear/SettingsWearActivity.kt | 22 +++++++ .../wear/views/SettingsWearMainView.kt | 22 +++++++ 17 files changed, 323 insertions(+), 29 deletions(-) create mode 100755 app/src/quest/AndroidManifest.xml create mode 100755 app/src/quest/java/io/homeassistant/companion/android/CrashHandling.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/launch/LaunchPresenterImpl.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/onboarding/MessagingToken.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/sensors/LocationSensorManager.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/settings/wear/SettingsWearActivity.kt create mode 100755 app/src/quest/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearMainView.kt diff --git a/.github/actions/inflate-secrets/action.yml b/.github/actions/inflate-secrets/action.yml index 817823169..d3e974d6e 100644 --- a/.github/actions/inflate-secrets/action.yml +++ b/.github/actions/inflate-secrets/action.yml @@ -21,6 +21,7 @@ runs: run: | cp .github/mock-google-services.json app/src/debug/google-services.json cp .github/mock-google-services.json app/src/minimal/google-services.json + cp .github/mock-google-services.json app/src/quest/google-services.json - name: Inflate release_keystore.keystore shell: bash diff --git a/.github/mock-google-services.json b/.github/mock-google-services.json index 78c8a0803..8dd8f6400 100644 --- a/.github/mock-google-services.json +++ b/.github/mock-google-services.json @@ -57,6 +57,32 @@ "current_key": "current_key" } ] + }, + { + "client_info": { + "mobilesdk_app_id": "mobilesdk_app_id", + "android_client_info": { + "package_name": "io.homeassistant.companion.android.quest" + } + }, + "api_key": [ + { + "current_key": "current_key" + } + ] + }, + { + "client_info": { + "mobilesdk_app_id": "mobilesdk_app_id", + "android_client_info": { + "package_name": "io.homeassistant.companion.android.quest.debug" + } + }, + "api_key": [ + { + "current_key": "current_key" + } + ] } ], "configuration_version": "1" diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index 589549b73..4e789687b 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -92,6 +92,16 @@ jobs: asset_name: home-assistant-minimal-${{steps.rel_number.outputs.version}}.apk asset_content_type: application/zip + - name: Upload Quest APK + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./app/build/outputs/apk/quest/release/app-quest-release.apk + asset_name: home-assistant-quest-${{steps.rel_number.outputs.version}}.apk + asset_content_type: application/zip + - name: Upload Wear APK uses: actions/upload-release-asset@v1 env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 133baa49b..05c3edc2f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,6 +91,16 @@ jobs: asset_name: home-assistant-minimal-${{steps.rel_number.outputs.version}}.apk asset_content_type: application/zip + - name: Upload Quest APK + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.get_release.outputs.upload_url }} + asset_path: ./app/build/outputs/apk/quest/release/app-quest-release.apk + asset_name: home-assistant-quest-${{steps.rel_number.outputs.version}}.apk + asset_content_type: application/zip + - name: Upload Wear APK uses: actions/upload-release-asset@v1 env: diff --git a/README.md b/README.md index 9f22dbe78..b5674334c 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,13 @@ If you are looking for documentation around the companion applications check out - Create a Firebase project at [Firebase Console](https://console.firebase.google.com) -- Create four Android apps, with following package names +- Create six Android apps, with following package names - `io.homeassistant.companion.android` - `io.homeassistant.companion.android.debug` - `io.homeassistant.companion.android.minimal` - `io.homeassistant.companion.android.minimal.debug` + - `io.homeassistant.companion.android.quest` + - `io.homeassistant.companion.android.quest.debug` - Now download the `google-services.json` file and put it in the _home-assistant-Android/app_ folder. This file contains the configuration of the whole project (all the four applications). @@ -55,7 +57,7 @@ homeAssistantAndroidRateLimitUrl=https://mydomain.cloudfunctions.net/checkRateLi ## App Flavors -The Android app has both a full flavor that uses Google Play Services to offer features like location tracking and notifications. There is also a minimal flavor that does not require Google Play Services and can be found in the releases section. The minimal flavor does not have location tracking or notifications. +The Android app has both a full flavor that uses Google Play Services to offer features like location tracking and notifications. There is also a minimal flavor that does not require Google Play Services and can be found in the releases section. The minimal flavor does not have location tracking or notifications. The quest flavor is identical to the minimal flavor with the exception of changes required for the device. ## Testing Dev Releases diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2d428d694..c08a08de3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -84,6 +84,11 @@ android { applicationIdSuffix = "" versionNameSuffix = "-full" } + create("quest") { + applicationIdSuffix = ".quest" + versionNameSuffix = "-quest" + minSdk = 23 + } // Generate a list of application ids into BuildConfig val values = productFlavors.joinToString { @@ -97,6 +102,9 @@ android { register("minimal") { enabled.set(false) } + register("quest") { + enabled.set(false) + } } testOptions { diff --git a/app/src/main/java/io/homeassistant/companion/android/launch/LaunchActivity.kt b/app/src/main/java/io/homeassistant/companion/android/launch/LaunchActivity.kt index e16c63278..75b414e93 100644 --- a/app/src/main/java/io/homeassistant/companion/android/launch/LaunchActivity.kt +++ b/app/src/main/java/io/homeassistant/companion/android/launch/LaunchActivity.kt @@ -100,7 +100,7 @@ class LaunchActivity : AppCompatActivity(), LaunchView { val deviceName = intent.getStringExtra("DeviceName").toString() val deviceTrackingEnabled = intent.getBooleanExtra("LocationTracking", false) val messagingToken = getMessagingToken() - if (messagingToken.isNullOrBlank()) { + if (messagingToken.isNullOrBlank() && BuildConfig.FLAVOR == "full") { AlertDialog.Builder(this@LaunchActivity) .setTitle(commonR.string.firebase_error_title) .setMessage(commonR.string.firebase_error_message) diff --git a/app/src/main/java/io/homeassistant/companion/android/settings/SettingsFragment.kt b/app/src/main/java/io/homeassistant/companion/android/settings/SettingsFragment.kt index 79275e5a6..ac8046d45 100644 --- a/app/src/main/java/io/homeassistant/companion/android/settings/SettingsFragment.kt +++ b/app/src/main/java/io/homeassistant/companion/android/settings/SettingsFragment.kt @@ -141,6 +141,7 @@ class SettingsFragment constructor( return@setOnPreferenceClickListener true } + findPreference("widgets")?.isVisible = BuildConfig.FLAVOR != "quest" findPreference("manage_widgets")?.setOnPreferenceClickListener { parentFragmentManager .beginTransaction() @@ -150,31 +151,33 @@ class SettingsFragment constructor( return@setOnPreferenceClickListener true } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - findPreference("shortcuts")?.let { - it.isVisible = true + if (BuildConfig.FLAVOR != "quest") { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + findPreference("shortcuts")?.let { + it.isVisible = true + } + findPreference("manage_shortcuts")?.setOnPreferenceClickListener { + parentFragmentManager + .beginTransaction() + .replace(R.id.content, ManageShortcutsSettingsFragment::class.java, null) + .addToBackStack(getString(commonR.string.shortcuts)) + .commit() + return@setOnPreferenceClickListener true + } } - findPreference("manage_shortcuts")?.setOnPreferenceClickListener { - parentFragmentManager - .beginTransaction() - .replace(R.id.content, ManageShortcutsSettingsFragment::class.java, null) - .addToBackStack(getString(commonR.string.shortcuts)) - .commit() - return@setOnPreferenceClickListener true - } - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - findPreference("quick_settings")?.let { - it.isVisible = true - } - findPreference("manage_tiles")?.setOnPreferenceClickListener { - parentFragmentManager - .beginTransaction() - .replace(R.id.content, ManageTilesFragment::class.java, null) - .addToBackStack(getString(commonR.string.tiles)) - .commit() - return@setOnPreferenceClickListener true + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + findPreference("quick_settings")?.let { + it.isVisible = true + } + findPreference("manage_tiles")?.setOnPreferenceClickListener { + parentFragmentManager + .beginTransaction() + .replace(R.id.content, ManageTilesFragment::class.java, null) + .addToBackStack(getString(commonR.string.tiles)) + .commit() + return@setOnPreferenceClickListener true + } } } @@ -217,7 +220,7 @@ class SettingsFragment constructor( } } findPreference("crash_reporting")?.let { - it.isVisible = true + it.isVisible = BuildConfig.FLAVOR == "full" it.setOnPreferenceChangeListener { _, newValue -> val checked = newValue as Boolean @@ -228,7 +231,7 @@ class SettingsFragment constructor( val pm = requireContext().packageManager val hasWearApp = pm.getLaunchIntentForPackage("com.google.android.wearable.app") val hasSamsungApp = pm.getLaunchIntentForPackage("com.samsung.android.app.watchmanager") - findPreference("wear_category")?.isVisible = hasWearApp != null || hasSamsungApp != null + findPreference("wear_category")?.isVisible = BuildConfig.FLAVOR == "full" && (hasWearApp != null || hasSamsungApp != null) findPreference("wear_settings")?.setOnPreferenceClickListener { startActivity(SettingsWearActivity.newInstance(requireContext())) return@setOnPreferenceClickListener true @@ -238,7 +241,7 @@ class SettingsFragment constructor( findPreference("changelog")?.let { val link = if (BuildConfig.VERSION_NAME.startsWith("LOCAL")) "https://github.com/home-assistant/android/releases" - else "https://github.com/home-assistant/android/releases/tag/${BuildConfig.VERSION_NAME.replace("-full", "").replace("-minimal", "")}" + else "https://github.com/home-assistant/android/releases/tag/${BuildConfig.VERSION_NAME.replace("-full", "").replace("-minimal", "").replace("-quest", "")}" it.summary = link it.intent = Intent(Intent.ACTION_VIEW, Uri.parse(link)) } diff --git a/app/src/quest/AndroidManifest.xml b/app/src/quest/AndroidManifest.xml new file mode 100755 index 000000000..09e81878a --- /dev/null +++ b/app/src/quest/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/app/src/quest/java/io/homeassistant/companion/android/CrashHandling.kt b/app/src/quest/java/io/homeassistant/companion/android/CrashHandling.kt new file mode 100755 index 000000000..fe5a5483b --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/CrashHandling.kt @@ -0,0 +1,7 @@ +package io.homeassistant.companion.android + +import android.content.Context + +fun initCrashReporting(context: Context, enabled: Boolean) { + // Noop +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/launch/LaunchPresenterImpl.kt b/app/src/quest/java/io/homeassistant/companion/android/launch/LaunchPresenterImpl.kt new file mode 100755 index 000000000..d1acaf417 --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/launch/LaunchPresenterImpl.kt @@ -0,0 +1,29 @@ +package io.homeassistant.companion.android.launch + +import android.util.Log +import io.homeassistant.companion.android.BuildConfig +import io.homeassistant.companion.android.common.data.authentication.AuthenticationRepository +import io.homeassistant.companion.android.common.data.integration.DeviceRegistration +import io.homeassistant.companion.android.common.data.integration.IntegrationRepository +import kotlinx.coroutines.launch +import javax.inject.Inject + +class LaunchPresenterImpl @Inject constructor( + view: LaunchView, + authenticationUseCase: AuthenticationRepository, + integrationUseCase: IntegrationRepository +) : LaunchPresenterBase(view, authenticationUseCase, integrationUseCase) { + override fun resyncRegistration() { + mainScope.launch { + try { + integrationUseCase.updateRegistration( + DeviceRegistration( + "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" + ) + ) + } catch (e: Exception) { + Log.e(TAG, "Issue updating Registration", e) + } + } + } +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/onboarding/MessagingToken.kt b/app/src/quest/java/io/homeassistant/companion/android/onboarding/MessagingToken.kt new file mode 100755 index 000000000..af93eb74b --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/onboarding/MessagingToken.kt @@ -0,0 +1,5 @@ +package io.homeassistant.companion.android.onboarding + +suspend fun getMessagingToken(): String { + return "" +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt b/app/src/quest/java/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt new file mode 100755 index 000000000..40acd6db8 --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt @@ -0,0 +1,32 @@ +package io.homeassistant.companion.android.sensors + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.R as commonR + +class ActivitySensorManager : BroadcastReceiver(), SensorManager { + + override fun onReceive(context: Context, intent: Intent) { + // Noop + } + + override val enabledByDefault: Boolean + get() = false + override val name: Int + get() = commonR.string.sensor_name_activity + + override fun getAvailableSensors(context: Context): List { + return listOf() + } + + override fun requiredPermissions(sensorId: String): Array { + // Noop + return emptyArray() + } + + override fun requestSensorUpdate(context: Context) { + // Noop + } +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt b/app/src/quest/java/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt new file mode 100755 index 000000000..171c9fb84 --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt @@ -0,0 +1,35 @@ +package io.homeassistant.companion.android.sensors + +import android.content.Context +import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.R as commonR + +class GeocodeSensorManager : SensorManager { + + companion object { + private const val TAG = "GeocodeSM" + val geocodedLocation = SensorManager.BasicSensor( + "geocoded_location", + "sensor", + commonR.string.basic_sensor_name_geolocation, + commonR.string.sensor_description_geocoded_location + ) + } + + override val enabledByDefault: Boolean + get() = false + override val name: Int + get() = commonR.string.sensor_name_geolocation + + override fun getAvailableSensors(context: Context): List { + return listOf() + } + + override fun requiredPermissions(sensorId: String): Array { + return emptyArray() + } + + override fun requestSensorUpdate(context: Context) { + // No op + } +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/sensors/LocationSensorManager.kt b/app/src/quest/java/io/homeassistant/companion/android/sensors/LocationSensorManager.kt new file mode 100755 index 000000000..e7c10f6f9 --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/sensors/LocationSensorManager.kt @@ -0,0 +1,65 @@ +package io.homeassistant.companion.android.sensors + +import android.content.Context +import android.content.Intent +import io.homeassistant.companion.android.common.sensors.LocationSensorManagerBase +import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.R as commonR + +class LocationSensorManager : LocationSensorManagerBase(), SensorManager { + + companion object { + const val MINIMUM_ACCURACY = 200 + + const val ACTION_REQUEST_LOCATION_UPDATES = + "io.homeassistant.companion.android.background.REQUEST_UPDATES" + const val ACTION_REQUEST_ACCURATE_LOCATION_UPDATE = + "io.homeassistant.companion.android.background.REQUEST_ACCURATE_UPDATE" + const val ACTION_PROCESS_LOCATION = + "io.homeassistant.companion.android.background.PROCESS_UPDATES" + const val ACTION_PROCESS_GEO = + "io.homeassistant.companion.android.background.PROCESS_GEOFENCE" + + val backgroundLocation = SensorManager.BasicSensor( + "location_background", + "", + commonR.string.basic_sensor_name_location_background, + commonR.string.sensor_description_location_background + ) + val zoneLocation = SensorManager.BasicSensor( + "zone_background", + "", + commonR.string.basic_sensor_name_location_zone, + commonR.string.sensor_description_location_zone + ) + val singleAccurateLocation = SensorManager.BasicSensor( + "accurate_location", + "", + commonR.string.basic_sensor_name_location_accurate, + commonR.string.sensor_description_location_accurate + ) + internal const val TAG = "LocBroadcastReceiver" + } + + override fun onReceive(context: Context, intent: Intent) { + // Noop + } + + override val enabledByDefault: Boolean + get() = false + override val name: Int + get() = commonR.string.sensor_name_location + + override fun getAvailableSensors(context: Context): List { + return listOf() + } + + override fun requiredPermissions(sensorId: String): Array { + // Noop + return emptyArray() + } + + override fun requestSensorUpdate(context: Context) { + // Noop + } +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/settings/wear/SettingsWearActivity.kt b/app/src/quest/java/io/homeassistant/companion/android/settings/wear/SettingsWearActivity.kt new file mode 100755 index 000000000..5b4375b53 --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/settings/wear/SettingsWearActivity.kt @@ -0,0 +1,22 @@ +package io.homeassistant.companion.android.settings.wear + +import android.content.Context +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import com.google.android.gms.wearable.CapabilityClient +import com.google.android.gms.wearable.CapabilityInfo + +class SettingsWearActivity : AppCompatActivity(), CapabilityClient.OnCapabilityChangedListener { + + override fun onCapabilityChanged(capabilityInfo: CapabilityInfo) { + // No op + } + + companion object { + private const val TAG = "SettingsWearAct" + + fun newInstance(context: Context): Intent { + return Intent(context, SettingsWearActivity::class.java) + } + } +} diff --git a/app/src/quest/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearMainView.kt b/app/src/quest/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearMainView.kt new file mode 100755 index 000000000..17431294b --- /dev/null +++ b/app/src/quest/java/io/homeassistant/companion/android/settings/wear/views/SettingsWearMainView.kt @@ -0,0 +1,22 @@ +package io.homeassistant.companion.android.settings + +import android.content.Context +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import com.google.android.gms.wearable.DataClient +import com.google.android.gms.wearable.DataEventBuffer + +class SettingsWearMainView : AppCompatActivity(), DataClient.OnDataChangedListener { + + companion object { + private const val TAG = "SettingsWearMainView" + + fun newInstance(context: Context): Intent { + return Intent(context, SettingsWearMainView::class.java) + } + } + + override fun onDataChanged(dataEvents: DataEventBuffer) { + // No op + } +}