From 842c0d764fdc40c381eac09499b7d6edd17df531 Mon Sep 17 00:00:00 2001 From: Tommaso Berlose Date: Sun, 10 May 2020 20:29:35 +0200 Subject: [PATCH] Add google fit connection --- app/google-services.json | 33 +++- .../anotherwidget/receivers/FenceReceiver.kt | 61 +++--- .../ui/fragments/GlanceTabFragment.kt | 181 ++++++++++-------- .../res/layout/fragment_glance_settings.xml | 1 - 4 files changed, 153 insertions(+), 123 deletions(-) diff --git a/app/google-services.json b/app/google-services.json index f4b7f2b..b01acdb 100644 --- a/app/google-services.json +++ b/app/google-services.json @@ -15,23 +15,38 @@ }, "oauth_client": [ { - "client_id": "791844924473-73dh46rorjq8vm97dgbn6can2dcpqlf0.apps.googleusercontent.com", - "client_type": 3 + "client_id": "791844924473-2lt64gf4jif7jb6s14igfql3ntosqj2s.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.tommasoberlose.anotherwidget", + "certificate_hash": "8c2a10e4c0663437206d2356d8e0e4047da70fb2" + } + }, + { + "client_id": "791844924473-7sq4es017gl6pldrpv0efv5avprgdfv2.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.tommasoberlose.anotherwidget", + "certificate_hash": "4a2735eca05bc73974f1bf80304bbee32b276196" + } + }, + { + "client_id": "791844924473-tsfd6idva64t5adh2atcfflpr0k52hlg.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.tommasoberlose.anotherwidget", + "certificate_hash": "82a38974264dca740d0612c9f9d15f15574cf160" + } } ], "api_key": [ { - "current_key": "AIzaSyAeJRXstqnzebibxmm3FRM98nbwE_kC8tA" + "current_key": "AIzaSyCT_v2Qw1zCWfmc_ywsovj_4poSXr7k5f0" } ], "services": { "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "791844924473-73dh46rorjq8vm97dgbn6can2dcpqlf0.apps.googleusercontent.com", - "client_type": 3 - } - ] + "other_platform_oauth_client": [] } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/FenceReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/FenceReceiver.kt index 9dc2231..53e6dee 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/FenceReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/FenceReceiver.kt @@ -10,6 +10,7 @@ import com.google.android.gms.fitness.Fitness import com.google.android.gms.fitness.FitnessOptions import com.google.android.gms.fitness.data.DataSource import com.google.android.gms.fitness.data.DataType +import com.google.android.gms.fitness.data.Field import com.google.android.gms.fitness.data.Field.FIELD_STEPS import com.google.android.gms.fitness.request.DataReadRequest import com.google.android.gms.location.ActivityTransitionResult @@ -35,49 +36,49 @@ class FenceReceiver : BroadcastReceiver() { } } - private fun requestDailySteps(context: Context) { - val fitnessOptions = FitnessOptions.builder() + private fun resetDailySteps() { + Preferences.googleFitSteps = -1 + } + + companion object { + val FITNESS_OPTIONS = FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ) .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ) .build() - val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context) + fun requestDailySteps(context: Context) { - Log.d("ciao", "hasPermission: ${GoogleSignIn.hasPermissions(account, fitnessOptions)}") + val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context) + if (account != null && GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) { - if (GoogleSignIn.hasPermissions(account, fitnessOptions)) { - val cal: Calendar = Calendar.getInstance() - cal.time = Date() - val endTime: Long = cal.timeInMillis - cal.add(Calendar.YEAR, -1) - val startTime: Long = cal.timeInMillis - val readRequest = DataReadRequest.Builder() - .aggregate( - DataType.TYPE_STEP_COUNT_DELTA, - DataType.AGGREGATE_STEP_COUNT_DELTA - ) - .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS) - .bucketByTime(1, TimeUnit.DAYS) - .build() + val cal: Calendar = Calendar.getInstance() + cal.set(Calendar.HOUR_OF_DAY, 0) + cal.set(Calendar.MINUTE, 0) + cal.set(Calendar.SECOND, 0) + cal.set(Calendar.MILLISECOND, 0) + val startTime: Long = cal.timeInMillis + + cal.add(Calendar.DAY_OF_YEAR, 1) + val endTime: Long = cal.timeInMillis + + val readRequest = DataReadRequest.Builder() + .aggregate( + DataType.TYPE_STEP_COUNT_DELTA, + DataType.AGGREGATE_STEP_COUNT_DELTA + ) + .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS) + .bucketByTime(1, TimeUnit.DAYS) + .build() - if (account != null) { Fitness.getHistoryClient(context, account) .readData(readRequest) .addOnSuccessListener { response -> - Preferences.googleFitSteps = - response.dataSets[0].dataPoints[0].getValue(FIELD_STEPS).asFloat() - .toLong() - Log.d("ciao", - "response: ${response.dataSets[0].dataPoints[0].getValue(FIELD_STEPS) - .asFloat().toLong()}" - ) + Preferences.googleFitSteps = response.buckets.sumBy { + it.getDataSet(DataType.AGGREGATE_STEP_COUNT_DELTA)?.dataPoints?.get(0)?.getValue(FIELD_STEPS)?.asInt() ?: 0 + }.toLong() MainWidget.updateWidget(context) } } } } - - private fun resetDailySteps() { - Preferences.googleFitSteps = -1 - } } \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt index 3919d41..a487ad5 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt @@ -10,6 +10,7 @@ import android.content.IntentFilter import android.content.pm.PackageManager import android.os.Build import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -22,8 +23,11 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInAccount +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.google.android.gms.common.api.ApiException import com.google.android.gms.fitness.FitnessOptions import com.google.android.gms.fitness.data.DataType +import com.google.android.gms.tasks.Task import com.karumi.dexter.Dexter import com.karumi.dexter.MultiplePermissionsReport import com.karumi.dexter.PermissionToken @@ -38,6 +42,8 @@ import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.AlarmHelper import com.tommasoberlose.anotherwidget.helpers.DailyStepsHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper +import com.tommasoberlose.anotherwidget.receivers.FenceReceiver +import com.tommasoberlose.anotherwidget.receivers.FenceReceiver.Companion.FITNESS_OPTIONS import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission @@ -110,12 +116,12 @@ class GlanceTabFragment : Fragment() { } }) -// viewModel.showDailySteps.observe(viewLifecycleOwner, Observer { -// maintainScrollPosition { -// show_steps_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible) -// } -// checkFitnessPermission() -// }) + viewModel.showDailySteps.observe(viewLifecycleOwner, Observer { + maintainScrollPosition { + show_steps_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible) + } + checkFitnessPermission() + }) viewModel.customInfo.observe(viewLifecycleOwner, Observer { maintainScrollPosition { @@ -191,7 +197,12 @@ class GlanceTabFragment : Fragment() { .addItem(getString(R.string.settings_visible), true) .addItem(getString(R.string.settings_not_visible), false) .addOnSelectItemListener { value -> - Preferences.showDailySteps = value + if (value) { + val mGoogleSignInClient = GoogleSignIn.getClient(requireActivity(), GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(FITNESS_OPTIONS).build()) + startActivityForResult(mGoogleSignInClient.signInIntent, 2) + } else { + Preferences.showDailySteps = false + } }.show() } } @@ -255,83 +266,87 @@ class GlanceTabFragment : Fragment() { } } -// private fun checkFitnessPermission() { -// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION) == true) { -// fitness_permission_alert?.isVisible = false -// if (Preferences.showDailySteps) { -// val fitnessOptions = FitnessOptions.builder() -// .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ) -// .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ) -// .build() -// -// val account: GoogleSignInAccount = GoogleSignIn.getLastSignedInAccount(requireContext()) ?: GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions) -// -// if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) { -// GoogleSignIn.requestPermissions( -// requireActivity(), -// 1, -// account, -// fitnessOptions) -// } else { -// DailyStepsHelper.registerFence(requireContext()) -// } -// } else { -// DailyStepsHelper.unregisterFence(requireContext()) -// } -// show_steps_label?.text = if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(R.string.settings_not_visible) -// } else if (Preferences.showDailySteps) { -// DailyStepsHelper.unregisterFence(requireContext()) -// fitness_permission_alert?.isVisible = true -// show_steps_label?.text = getString(R.string.settings_request_fitness_access) -// fitness_permission_alert?.setOnClickListener { -// requireFitnessPermission() -// } -// } else { -// DailyStepsHelper.unregisterFence(requireContext()) -// show_steps_label?.text = getString(R.string.settings_not_visible) -// fitness_permission_alert?.isVisible = false -// } -// } -// -// override fun onActivityResult( -// requestCode: Int, -// resultCode: Int, -// data: Intent? -// ) { -// if (resultCode == Activity.RESULT_OK) { -// if (requestCode == 1) { -// DailyStepsHelper.registerFence(requireContext()) -// } else { -// Preferences.showDailySteps = false -// } -// } -// } + private fun checkFitnessPermission() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION) == true) { + fitness_permission_alert?.isVisible = false + if (Preferences.showDailySteps) { + DailyStepsHelper.registerFence(requireContext()) + } else { + DailyStepsHelper.unregisterFence(requireContext()) + } + show_steps_label?.text = if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(R.string.settings_not_visible) + } else if (Preferences.showDailySteps) { + DailyStepsHelper.unregisterFence(requireContext()) + fitness_permission_alert?.isVisible = true + show_steps_label?.text = getString(R.string.settings_request_fitness_access) + fitness_permission_alert?.setOnClickListener { + requireFitnessPermission() + } + } else { + DailyStepsHelper.unregisterFence(requireContext()) + show_steps_label?.text = getString(R.string.settings_not_visible) + fitness_permission_alert?.isVisible = false + } + } -// private fun requireFitnessPermission() { -// Dexter.withContext(requireContext()) -// .withPermissions( -// "com.google.android.gms.permission.ACTIVITY_RECOGNITION", -// "android.gms.permission.ACTIVITY_RECOGNITION", -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACTIVITY_RECOGNITION else "com.google.android.gms.permission.ACTIVITY_RECOGNITION" -// ).withListener(object: MultiplePermissionsListener { -// override fun onPermissionsChecked(report: MultiplePermissionsReport?) { -// report?.let { -// if (report.areAllPermissionsGranted()){ -// checkFitnessPermission() -// } -// } -// } -// override fun onPermissionRationaleShouldBeShown( -// permissions: MutableList?, -// token: PermissionToken? -// ) { -// // Remember to invoke this method when the custom rationale is closed -// // or just by default if you don't want to use any custom rationale. -// token?.continuePermissionRequest() -// } -// }) -// .check() -// } + override fun onActivityResult( + requestCode: Int, + resultCode: Int, + data: Intent? + ) { + when (requestCode) { + 1 -> { + if (resultCode == Activity.RESULT_OK) { + DailyStepsHelper.registerFence(requireContext()) + } else { + Preferences.showDailySteps = false + } + } + 2-> { + try { + val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(data).getResult(ApiException::class.java) + if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) { + GoogleSignIn.requestPermissions( + requireActivity(), + 1, + account, + FITNESS_OPTIONS) + } else { + DailyStepsHelper.registerFence(requireContext()) + } + } catch (e: ApiException) { + e.printStackTrace() + Preferences.showDailySteps = false + } + } + } + } + + private fun requireFitnessPermission() { + Dexter.withContext(requireContext()) + .withPermissions( + "com.google.android.gms.permission.ACTIVITY_RECOGNITION", + "android.gms.permission.ACTIVITY_RECOGNITION", + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACTIVITY_RECOGNITION else "com.google.android.gms.permission.ACTIVITY_RECOGNITION" + ).withListener(object: MultiplePermissionsListener { + override fun onPermissionsChecked(report: MultiplePermissionsReport?) { + report?.let { + if (report.areAllPermissionsGranted()){ + checkFitnessPermission() + } + } + } + override fun onPermissionRationaleShouldBeShown( + permissions: MutableList?, + token: PermissionToken? + ) { + // Remember to invoke this method when the custom rationale is closed + // or just by default if you don't want to use any custom rationale. + token?.continuePermissionRequest() + } + }) + .check() + } private fun maintainScrollPosition(callback: () -> Unit) { val scrollPosition = scrollView.scrollY diff --git a/app/src/main/res/layout/fragment_glance_settings.xml b/app/src/main/res/layout/fragment_glance_settings.xml index 9c1ab55..a795164 100644 --- a/app/src/main/res/layout/fragment_glance_settings.xml +++ b/app/src/main/res/layout/fragment_glance_settings.xml @@ -194,7 +194,6 @@ android:paddingRight="8dp" android:clickable="true" android:focusable="true" - android:visibility="gone" android:background="?android:attr/selectableItemBackground" android:gravity="center_vertical" android:id="@+id/action_show_steps"