1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * 17 */ 18 19 package com.android.healthconnect.controller.onboarding 20 21 import android.app.Activity 22 import android.content.Context 23 import android.content.Intent 24 import android.os.Bundle 25 import android.view.LayoutInflater 26 import android.view.View 27 import android.view.WindowManager 28 import android.widget.Button 29 import android.widget.FrameLayout 30 import android.widget.TextView 31 import androidx.fragment.app.FragmentActivity 32 import com.android.healthconnect.controller.R 33 import com.android.healthconnect.controller.shared.Constants.ONBOARDING_SHOWN_PREF_KEY 34 import com.android.healthconnect.controller.shared.Constants.USER_ACTIVITY_TRACKER 35 import com.android.healthconnect.controller.utils.logging.HealthConnectLogger 36 import com.android.healthconnect.controller.utils.logging.OnboardingElement 37 import com.android.healthconnect.controller.utils.logging.PageName 38 import com.android.healthfitness.flags.AconfigFlagHelper.isPersonalHealthRecordEnabled 39 import com.android.settingslib.collapsingtoolbar.EdgeToEdgeUtils 40 import com.android.settingslib.widget.SettingsThemeHelper 41 import dagger.hilt.android.AndroidEntryPoint 42 import javax.inject.Inject 43 44 /** Onboarding activity for Health Connect. */ 45 @AndroidEntryPoint(FragmentActivity::class) 46 class OnboardingActivity : Hilt_OnboardingActivity() { 47 48 /** Companion object for OnboardingActivity. */ 49 companion object { 50 private const val TARGET_ACTIVITY_INTENT = "ONBOARDING_TARGET_ACTIVITY_INTENT" 51 52 /** A utility function designed solely for testing purposes. */ disableOnboardingnull53 fun disableOnboarding(context: Context) { 54 val editor = 55 context.getSharedPreferences(USER_ACTIVITY_TRACKER, Context.MODE_PRIVATE).edit() 56 editor.putBoolean(ONBOARDING_SHOWN_PREF_KEY, true) 57 editor.commit() 58 } 59 shouldRedirectToOnboardingActivitynull60 fun shouldRedirectToOnboardingActivity(activity: Activity): Boolean { 61 val sharedPreference = 62 activity.getSharedPreferences(USER_ACTIVITY_TRACKER, Context.MODE_PRIVATE) 63 val previouslyOpened = sharedPreference.getBoolean(ONBOARDING_SHOWN_PREF_KEY, false) 64 return !previouslyOpened 65 } 66 createIntentnull67 fun createIntent(context: Context, targetIntent: Intent? = null): Intent { 68 val flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NO_ANIMATION 69 70 return Intent(context, OnboardingActivity::class.java).apply { 71 addFlags(flags) 72 if (targetIntent != null) { 73 putExtra(TARGET_ACTIVITY_INTENT, targetIntent) 74 } 75 } 76 } 77 } 78 79 @Inject lateinit var logger: HealthConnectLogger 80 81 private var targetIntent: Intent? = null 82 onCreatenull83 override fun onCreate(savedInstanceState: Bundle?) { 84 EdgeToEdgeUtils.enable(this) 85 if (SettingsThemeHelper.isExpressiveTheme(this)) { 86 setTheme(R.style.Theme_HealthConnect_Expressive) 87 } 88 super.onCreate(savedInstanceState) 89 // This flag ensures a non system app cannot show an overlay on Health Connect. b/313425281 90 window.addSystemFlags( 91 WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS 92 ) 93 if (intent.hasExtra(TARGET_ACTIVITY_INTENT)) { 94 targetIntent = intent.getParcelableExtra(TARGET_ACTIVITY_INTENT) 95 } 96 97 logger.setPageId(PageName.ONBOARDING_PAGE) 98 99 setupOnboardingScreen() 100 } 101 onResumenull102 override fun onResume() { 103 super.onResume() 104 logger.logPageImpression() 105 } 106 setupOnboardingScreennull107 private fun setupOnboardingScreen() { 108 setContentView(R.layout.onboarding_screen) 109 110 val onboardingDescription = findViewById<TextView>(R.id.onboarding_description) 111 val withHealthConnectTitle = 112 findViewById<TextView>(R.id.onboarding_description_with_health_connect) 113 if (isPersonalHealthRecordEnabled()) { 114 onboardingDescription.setText(R.string.onboarding_description_health_records) 115 withHealthConnectTitle.visibility = View.VISIBLE 116 logger.logImpression(OnboardingElement.ONBOARDING_MESSAGE_WITH_PHR) 117 } else { 118 onboardingDescription.setText(R.string.onboarding_description) 119 withHealthConnectTitle.visibility = View.GONE 120 } 121 122 setupButtonArea() 123 } 124 setupButtonAreanull125 private fun setupButtonArea() { 126 val buttonArea = findViewById<FrameLayout>(R.id.button_area) 127 val buttonLayoutId = 128 if (SettingsThemeHelper.isExpressiveTheme(this)) { 129 R.layout.widget_setup_bottom_button_bar_expressive 130 } else { 131 R.layout.widget_setup_bottom_button_bar_legacy 132 } 133 buttonArea.addView(LayoutInflater.from(this).inflate(buttonLayoutId, buttonArea, false)) 134 135 val goBackButton = findViewById<Button>(R.id.secondary_button) 136 goBackButton.text = getString(R.string.onboarding_go_back_button_text) 137 val getStartedButton = findViewById<Button>(R.id.primary_button_full) 138 getStartedButton.text = getString(R.string.onboarding_get_started_button_text) 139 logger.logImpression(OnboardingElement.ONBOARDING_GO_BACK_BUTTON) 140 logger.logImpression(OnboardingElement.ONBOARDING_COMPLETED_BUTTON) 141 142 goBackButton.setOnClickListener { 143 logger.logInteraction(OnboardingElement.ONBOARDING_GO_BACK_BUTTON) 144 setResult(Activity.RESULT_CANCELED) 145 finish() 146 } 147 148 val sharedPreference = getSharedPreferences(USER_ACTIVITY_TRACKER, Context.MODE_PRIVATE) 149 getStartedButton.setOnClickListener { 150 logger.logInteraction(OnboardingElement.ONBOARDING_COMPLETED_BUTTON) 151 val editor = sharedPreference.edit() 152 editor.putBoolean(ONBOARDING_SHOWN_PREF_KEY, true) 153 editor.apply() 154 if (targetIntent == null) { 155 setResult(Activity.RESULT_OK) 156 } else { 157 startActivity(targetIntent) 158 } 159 finish() 160 } 161 } 162 } 163