Add google fit integration

This commit is contained in:
Tommaso Berlose 2020-05-10 14:08:40 +02:00
parent 9a63b9bde2
commit 1754b4045b
28 changed files with 713 additions and 335 deletions

Binary file not shown.

2
.idea/gradle.xml generated
View File

@ -11,8 +11,6 @@
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/googlefit" />
<option value="$PROJECT_DIR$/tasksintegration" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />

2
.idea/modules.xml generated
View File

@ -4,8 +4,6 @@
<modules>
<module fileurl="file://$PROJECT_DIR$/Another Widget.iml" filepath="$PROJECT_DIR$/Another Widget.iml" group="Another Widget" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" group="Another Widget/app" />
<module fileurl="file://$PROJECT_DIR$/googlefit/googlefit.iml" filepath="$PROJECT_DIR$/googlefit/googlefit.iml" group="Another Widget/googlefit" />
<module fileurl="file://$PROJECT_DIR$/tasksintegration/tasksintegration.iml" filepath="$PROJECT_DIR$/tasksintegration/tasksintegration.iml" group="Another Widget/tasksintegration" />
</modules>
</component>
</project>

View File

@ -10,6 +10,10 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'realm-android'
def apiKeyPropertiesFile = rootProject.file("apikey.properties")
def apiKeyProperties = new Properties()
apiKeyProperties.load(new FileInputStream(apiKeyPropertiesFile))
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
@ -18,10 +22,12 @@ android {
applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23
targetSdkVersion 29
versionCode 83
versionName "2.0.6"
versionCode 84
versionName "2.0.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [ "AWARENESS_API_KEY": apiKeyProperties['AWARENESS_API_KEY']]
}
buildTypes {
@ -52,10 +58,6 @@ android {
}
viewBinding.enabled = true
dynamicFeatures = [":tasksintegration", ":googlefit"]
}
dependencies {
@ -98,6 +100,10 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0'
// Fitness
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
implementation 'com.google.android.gms:play-services-auth:18.0.0'
//Weather
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
implementation 'com.google.android.gms:play-services-location:17.0.0'

Binary file not shown.

View File

@ -10,6 +10,10 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<application
android:allowBackup="true"
@ -157,6 +161,18 @@
<action android:name="android.intent.action.BATTERY_OKAY"/>
</intent-filter>
</receiver>
<receiver android:name=".receivers.FenceReceiver"
android:exported="false"
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
<intent-filter>
<action android:name="com.mypackage.ACTION_PROCESS_ACTIVITY_TRANSITIONS" />
</intent-filter>
</receiver>
<meta-data
android:name="com.google.android.awareness.API_KEY"
android:value="${AWARENESS_API_KEY}"/>
</application>
</manifest>

View File

@ -1,6 +1,7 @@
package com.tommasoberlose.anotherwidget
import android.app.Application
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import com.chibatching.kotpref.Kotpref
import com.google.firebase.crashlytics.FirebaseCrashlytics

View File

@ -18,8 +18,8 @@ object Constants {
enum class GlanceProviderId(val id: String) {
PLAYING_SONG("PLAYING_SONG"),
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
// BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
CUSTOM_INFO("CUSTOM_INFO"),
// GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
}
}

View File

@ -83,6 +83,7 @@ object Preferences : KotprefModel() {
var showBatteryCharging by booleanPref(default = false)
var isBatteryLevelLow by booleanPref(default = false)
var googleFitSteps by longPref(default = -1)
var showDailySteps by booleanPref(default = false)
var showMusic by booleanPref(default = false)
var mediaInfoFormat by stringPref(default = "")

View File

@ -0,0 +1,97 @@
package com.tommasoberlose.anotherwidget.helpers
import android.Manifest
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import com.google.android.gms.location.ActivityRecognition
import com.google.android.gms.location.ActivityTransition
import com.google.android.gms.location.ActivityTransitionRequest
import com.google.android.gms.location.DetectedActivity
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.receivers.FenceReceiver
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
object DailyStepsHelper {
fun registerFence(context: Context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION)) {
val transitions = mutableListOf<ActivityTransition>()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.RUNNING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.RUNNING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build()
transitions +=
ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
val request = ActivityTransitionRequest(transitions)
// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
val task = ActivityRecognition.getClient(context)
.requestActivityTransitionUpdates(
request,
PendingIntent.getBroadcast(
context,
2,
Intent(context, FenceReceiver::class.java),
0
)
)
task.addOnFailureListener { e: Exception ->
e.printStackTrace()
Preferences.showDailySteps = false
}
}
}
fun unregisterFence(context: Context) {
val task = ActivityRecognition.getClient(context)
.removeActivityTransitionUpdates(
PendingIntent.getBroadcast(
context,
2,
Intent(context, FenceReceiver::class.java),
0
)
)
task.addOnCompleteListener {
if (it.isSuccessful) {
PendingIntent.getBroadcast(
context,
2,
Intent(context, FenceReceiver::class.java),
0
).cancel()
}
}
}
}

View File

@ -53,18 +53,18 @@ object GlanceProviderHelper {
R.drawable.round_notes
)
}
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
// GlanceProvider(providerId.id,
// context.getString(R.string.settings_low_battery_level_title),
// R.drawable.round_battery_charging_full
// )
// }
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
// GlanceProvider(providerId.id,
// context.getString(R.string.settings_daily_steps_title),
// R.drawable.round_directions_walk
// )
// }
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_low_battery_level_title),
R.drawable.round_battery_charging_full
)
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_daily_steps_title),
R.drawable.round_directions_walk
)
}
}
}
@ -72,13 +72,13 @@ object GlanceProviderHelper {
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
}
fun showSpecialWeather(context: Context): Boolean {
return EventRepository(context).getEventsCount() == 0 && (
fun showGlanceProviders(context: Context): Boolean {
return Preferences.showGlance && EventRepository(context).getEventsCount() == 0 && (
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
(Preferences.isBatteryLevelLow) ||
(Preferences.customNotes.isNotEmpty()) ||
(Preferences.googleFitSteps > 0)
(Preferences.showDailySteps && Preferences.googleFitSteps > 0)
)
}
}

View File

@ -0,0 +1,83 @@
package com.tommasoberlose.anotherwidget.receivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
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.FIELD_STEPS
import com.google.android.gms.fitness.request.DataReadRequest
import com.google.android.gms.location.ActivityTransitionResult
import com.google.android.gms.location.DetectedActivity
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import java.util.*
import java.util.concurrent.TimeUnit
class FenceReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (ActivityTransitionResult.hasResult(intent)) {
val result = ActivityTransitionResult.extractResult(intent)!!
val lastEvent = result.transitionEvents.last()
if (lastEvent.activityType == DetectedActivity.WALKING || lastEvent.activityType == DetectedActivity.RUNNING) {
requestDailySteps(context)
} else {
resetDailySteps()
}
}
}
private fun requestDailySteps(context: Context) {
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(context)
Log.d("ciao", "hasPermission: ${GoogleSignIn.hasPermissions(account, fitnessOptions)}")
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()
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()}"
)
MainWidget.updateWidget(context)
}
}
}
}
private fun resetDailySteps() {
Preferences.googleFitSteps = -1
}
}

View File

@ -26,6 +26,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.Navigation
import com.chibatching.kotpref.Kotpref
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.tabs.TabLayoutMediator
import com.karumi.dexter.Dexter

View File

@ -135,12 +135,6 @@ class CalendarTabFragment : Fragment() {
}
})
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
date_format_label?.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
}
})
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
calendar_app_label?.text = if (it != "") it else getString(R.string.default_calendar_app)
@ -290,27 +284,6 @@ class CalendarTabFragment : Fragment() {
}
}
action_date_format.setOnClickListener {
if (Preferences.showEvents) {
val now = Calendar.getInstance()
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
dialog.addItem(DateHelper.getDefaultDateText(requireContext(), now), "")
if (Preferences.dateFormat != "") {
dialog.addItem(DateHelper.getDateText(requireContext(), now), Preferences.dateFormat)
}
dialog.addItem(getString(R.string.custom_date_format), "-")
dialog.addOnSelectItemListener { value ->
if (value == "-") {
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
} else {
Preferences.dateFormat = value
}
}.show()
}
}
action_open_event_details.setOnClickListener {
if (Preferences.showEvents) {
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_event_app_title)).setSelectedValue(Preferences.openEventDetails)

View File

@ -21,7 +21,9 @@ import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.helpers.DateHelper
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import kotlinx.android.synthetic.main.fragment_general_settings.*
@ -29,6 +31,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.*
class GeneralTabFragment : Fragment() {
@ -141,6 +144,12 @@ class GeneralTabFragment : Fragment() {
}
})
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
date_format_label?.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
}
})
viewModel.customFont.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
@ -202,6 +211,27 @@ class GeneralTabFragment : Fragment() {
).show()
}
action_date_format.setOnClickListener {
if (Preferences.showEvents) {
val now = Calendar.getInstance()
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
dialog.addItem(DateHelper.getDefaultDateText(requireContext(), now), "")
if (Preferences.dateFormat != "") {
dialog.addItem(DateHelper.getDateText(requireContext(), now), Preferences.dateFormat)
}
dialog.addItem(getString(R.string.custom_date_format), "-")
dialog.addOnSelectItemListener { value ->
if (value == "-") {
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
} else {
Preferences.dateFormat = value
}
}.show()
}
}
action_background_color.setOnClickListener {
BottomSheetColorPicker(requireContext(),
colors = colors,

View File

@ -1,31 +1,34 @@
package com.tommasoberlose.anotherwidget.ui.fragments
import android.Manifest
import android.app.Activity
import android.app.AlarmManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
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
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.fitness.FitnessOptions
import com.google.android.gms.fitness.data.DataType
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
@ -33,16 +36,14 @@ import com.tommasoberlose.anotherwidget.components.GlanceProviderSortMenu
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
import com.tommasoberlose.anotherwidget.helpers.DailyStepsHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.models.GlanceProvider
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.idik.lib.slimadapter.SlimAdapter
import java.util.*
class GlanceTabFragment : Fragment() {
@ -109,6 +110,13 @@ 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.customInfo.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_custom_notes_label?.text = if (it == "") getString(R.string.settings_not_visible) else it
@ -174,6 +182,20 @@ class GlanceTabFragment : Fragment() {
}
}
action_show_steps.setOnClickListener {
if (Preferences.showGlance) {
BottomSheetMenu<Boolean>(
requireContext(),
header = getString(R.string.settings_daily_steps_title)
).setSelectedValue(Preferences.showDailySteps)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showDailySteps = value
}.show()
}
}
action_show_custom_notes.setOnClickListener {
if (Preferences.showGlance) {
CustomNotesDialog(requireContext()).show()
@ -228,11 +250,89 @@ class GlanceTabFragment : Fragment() {
activity?.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
}
} else {
show_music_label?.text = getString(R.string.settings_show_music_disabled_subtitle)
show_music_label?.text = getString(R.string.settings_not_visible)
notification_permission_alert?.isVisible = 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) {
// 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 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<PermissionRequest>?,
// 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
callback.invoke()

View File

@ -124,143 +124,156 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
private fun updateUI() {
uiJob?.cancel()
if (preview != null) {
preview.clearAnimation()
time_container.clearAnimation()
if (Preferences.showPreview) {
preview.setCardBackgroundColor(
ContextCompat.getColor(
requireContext(),
if (ColorHelper.getFontColor()
.isColorDark()
) android.R.color.white else R.color.colorAccent
)
)
widget_shape_background.setImageDrawable(BitmapHelper.getTintedDrawable(requireContext(), R.drawable.card_background, ColorHelper.getBackgroundColor()))
uiJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
val generatedView = MainWidget.generateWidgetView(requireContext())
withContext(Dispatchers.Main) {
generatedView.measure(0, 0)
preview.measure(0, 0)
}
val bitmap = BitmapHelper.getBitmapFromView(
generatedView,
if (preview.width > 0) preview.width else generatedView.measuredWidth,
generatedView.measuredHeight
)
withContext(Dispatchers.Main) {
// Clock
time.setTextColor(ColorHelper.getClockFontColor())
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
time.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(requireContext())
if (Preferences.showPreview) {
preview.setCardBackgroundColor(
ContextCompat.getColor(
requireContext(),
if (ColorHelper.getFontColor()
.isColorDark()
) android.R.color.white else R.color.colorAccent
)
time_am_pm.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
)
widget_shape_background?.setImageDrawable(
BitmapHelper.getTintedDrawable(
requireContext(),
R.drawable.card_background,
ColorHelper.getBackgroundColor()
)
time_am_pm.isVisible = Preferences.showAMPMIndicator
)
uiJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
val generatedView = MainWidget.generateWidgetView(requireContext())
// Clock bottom margin
clock_bottom_margin_none.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
clock_bottom_margin_small.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
clock_bottom_margin_medium.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
clock_bottom_margin_large.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
withContext(Dispatchers.Main) {
generatedView.measure(0, 0)
preview.measure(0, 0)
}
if ((Preferences.showClock && !time_container.isVisible) || (!Preferences.showClock && time_container.isVisible)) {
if (Preferences.showClock) {
val bitmap = BitmapHelper.getBitmapFromView(
generatedView,
if (preview.width > 0) preview.width else generatedView.measuredWidth,
generatedView.measuredHeight
)
withContext(Dispatchers.Main) {
// Clock
time.setTextColor(ColorHelper.getClockFontColor())
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
time.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(requireContext())
)
time_am_pm.setTextSize(
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
)
time_am_pm.isVisible = Preferences.showAMPMIndicator
// Clock bottom margin
clock_bottom_margin_none.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
clock_bottom_margin_small.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
clock_bottom_margin_medium.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
clock_bottom_margin_large.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
if ((Preferences.showClock && !time_container.isVisible) || (!Preferences.showClock && time_container.isVisible)) {
if (Preferences.showClock) {
time_container.layoutParams = time_container.layoutParams.apply {
height = RelativeLayout.LayoutParams.WRAP_CONTENT
}
time_container.measure(0, 0)
}
val initialHeight = time_container.measuredHeight
ValueAnimator.ofFloat(
if (Preferences.showClock) 0f else 1f,
if (Preferences.showClock) 1f else 0f
).apply {
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Float
time_container.layoutParams =
time_container.layoutParams.apply {
height = (initialHeight * animatedValue).toInt()
}
time.alpha = animatedValue
}
addListener(
onStart = {
if (Preferences.showClock) {
time_container.isVisible = true
}
},
onEnd = {
if (!Preferences.showClock) {
time_container.isVisible = false
}
}
)
}.start()
ValueAnimator.ofInt(
preview.height,
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
requireContext()
) else 0
).apply {
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
} else {
time_container.layoutParams = time_container.layoutParams.apply {
height = RelativeLayout.LayoutParams.WRAP_CONTENT
}
time_container.measure(0, 0)
}
val initialHeight = time_container.measuredHeight
ValueAnimator.ofFloat(
if (Preferences.showClock) 0f else 1f,
if (Preferences.showClock) 1f else 0f
).apply {
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Float
time_container.layoutParams = time_container.layoutParams.apply {
height = (initialHeight * animatedValue).toInt()
}
}
addListener(
onStart = {
if (Preferences.showClock) {
time_container.isVisible = true
}
},
onEnd = {
if (!Preferences.showClock) {
time_container.isVisible = false
}
}
)
}.start()
ValueAnimator.ofInt(
preview.height,
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
requireContext()
) else 0
).apply {
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
} else {
time_container.layoutParams = time_container.layoutParams.apply {
height = RelativeLayout.LayoutParams.WRAP_CONTENT
if (preview.height == 0) {
ValueAnimator.ofInt(
preview.height,
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
requireContext()
) else 0
).apply {
duration = 300L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
}
time_container.measure(0, 0)
}
if (preview.height == 0) {
ValueAnimator.ofInt(
preview.height,
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
requireContext()
) else 0
).apply {
duration = 300L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
widget_loader.animate().scaleX(0f).scaleY(0f).alpha(0f).setDuration(200L)
.start()
bitmap_container.setImageBitmap(bitmap)
widget.animate().alpha(1f).start()
}
widget_loader.animate().scaleX(0f).scaleY(0f).alpha(0f).setDuration(200L).start()
bitmap_container.setImageBitmap(bitmap)
widget.animate().alpha(1f).start()
}
} else {
ValueAnimator.ofInt(
preview.height,
0
).apply {
duration = 300L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
}
} else {
ValueAnimator.ofInt(
preview.height,
0
).apply {
duration = 300L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
}
showErrorBadge()
@ -277,8 +290,16 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
val metrics = DisplayMetrics()
act.windowManager.defaultDisplay.getMetrics(metrics)
height = metrics.heightPixels
width = (wallpaper?.intrinsicWidth ?: 1) * metrics.heightPixels / (wallpaper?.intrinsicWidth ?: 1)
var newHeight = metrics.heightPixels
var newWidth = (wallpaper?.intrinsicWidth ?: 1) * metrics.heightPixels / (wallpaper?.intrinsicHeight ?: 1)
if (newWidth < metrics.widthPixels) {
newWidth = metrics.widthPixels
newHeight = (wallpaper?.intrinsicHeight ?: 1) * metrics.widthPixels / (wallpaper?.intrinsicWidth ?: 1)
}
height = newHeight
width = newWidth
}
}
})
@ -313,11 +334,6 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}?.isVisible = Preferences.showMusic && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)
}
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
updateUI()
MainWidget.updateWidget(requireContext())
}
override fun onResume() {
super.onResume()
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
@ -332,10 +348,29 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
super.onPause()
}
var delayJob: Job? = null
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
delayJob?.cancel()
delayJob = lifecycleScope.launch(Dispatchers.IO) {
delay(200)
withContext(Dispatchers.Main) {
updateUI()
}
}
MainWidget.updateWidget(requireContext())
}
class UpdateUiMessageEvent
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
updateUI()
delayJob?.cancel()
delayJob = lifecycleScope.launch(Dispatchers.IO) {
delay(200)
withContext(Dispatchers.Main) {
updateUI()
}
}
}
}

View File

@ -4,6 +4,7 @@ import android.Manifest
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

View File

@ -58,6 +58,7 @@ class MainViewModel : ViewModel() {
val showMusic = Preferences.asLiveData(Preferences::showMusic)
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
val showBatteryCharging = Preferences.asLiveData(Preferences::showBatteryCharging)
val showDailySteps = Preferences.asLiveData(Preferences::showDailySteps)
val customInfo = Preferences.asLiveData(Preferences::customNotes)
// Advanced Settings

View File

@ -12,7 +12,6 @@ import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.text.format.DateUtils
import android.util.Log
import android.util.TypedValue
import android.view.View
import android.widget.ImageView
@ -261,12 +260,7 @@ class MainWidget : AppWidgetProvider() {
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
} else if (Preferences.showGlance) {
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders()) {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
@ -293,28 +287,28 @@ class MainWidget : AppWidgetProvider() {
break@loop
}
}
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
// if (Preferences.isBatteryLevelLow) {
// val alarmIntent = PendingIntent.getActivity(
// context,
// widgetID,
// IntentHelper.getClockIntent(context),
// 0
// )
// views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
// break@loop
// }
// }
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
if (Preferences.isBatteryLevelLow) {
val alarmIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getClockIntent(context),
0
)
views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
break@loop
}
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
if (Preferences.customNotes.isNotEmpty()) {
break@loop
}
}
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
// if (Preferences.googleFitSteps > 0) {
// break@loop
// }
// }
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
break@loop
}
}
}
}
@ -371,7 +365,7 @@ class MainWidget : AppWidgetProvider() {
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
)
if (GlanceProviderHelper.showSpecialWeather(context)) {
if (GlanceProviderHelper.showGlanceProviders(context)) {
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
} else {
views.setViewVisibility(R.id.special_weather_rect, View.GONE)
@ -524,7 +518,7 @@ class MainWidget : AppWidgetProvider() {
v.empty_layout.visibility = View.GONE
v.calendar_layout.visibility = View.VISIBLE
} else if (Preferences.showGlance) {
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
v.second_row_icon.isVisible = true
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders()) {
when (provider) {
@ -552,18 +546,18 @@ class MainWidget : AppWidgetProvider() {
break@loop
}
}
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
// if (Preferences.isBatteryLevelLow) {
// v.second_row_icon.setImageDrawable(
// ContextCompat.getDrawable(
// context,
// R.drawable.round_battery_charging_full
// )
// )
// v.next_event_date.text = context.getString(R.string.battery_low_warning)
// break@loop
// }
// }
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
if (Preferences.isBatteryLevelLow) {
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_battery_charging_full
)
)
v.next_event_date.text = context.getString(R.string.battery_low_warning)
break@loop
}
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
if (Preferences.customNotes.isNotEmpty()) {
v.second_row_icon.isVisible = false
@ -571,18 +565,18 @@ class MainWidget : AppWidgetProvider() {
break@loop
}
}
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
// if (Preferences.googleFitSteps > 0) {
// v.second_row_icon.setImageDrawable(
// ContextCompat.getDrawable(
// context,
// R.drawable.round_directions_walk
// )
// )
// v.next_event_date.text = ""
// break@loop
// }
// }
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_directions_walk
)
)
v.next_event_date.text = "${Preferences.googleFitSteps}"
break@loop
}
}
}
}
@ -694,7 +688,7 @@ class MainWidget : AppWidgetProvider() {
v.calendar_temp.text = currentTemp
v.special_temp.text = currentTemp
if (GlanceProviderHelper.showSpecialWeather(context)) {
if (GlanceProviderHelper.showGlanceProviders(context)) {
v.calendar_weather.visibility = View.GONE
} else {
v.special_weather.visibility = View.GONE

View File

@ -214,43 +214,6 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_show_multiple_events"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_code"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_show_multiple_events_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/show_multiple_events_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -325,43 +288,6 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_date_format"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="10dp"
android:src="@drawable/round_text_format"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_date_format_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/date_format_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -399,6 +325,43 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_show_multiple_events"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_code"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_show_multiple_events_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/show_multiple_events_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -166,6 +166,43 @@
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_date_format"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="10dp"
android:src="@drawable/round_text_format"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_date_format_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/date_format_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -185,6 +185,60 @@
android:textColor="@color/warningColorText" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
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"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_directions_walk"
android:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_daily_steps_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/show_steps_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="36dp"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:letterSpacing="0"
android:textAllCaps="false"
android:clickable="true"
android:layout_marginStart="-8dp"
android:layout_marginBottom="-8dp"
android:paddingBottom="0dp"
android:paddingTop="0dp"
android:focusable="true"
android:visibility="gone"
android:id="@+id/fitness_permission_alert"
android:textColor="@color/errorColorText"
android:text="@string/action_grant_permission"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -207,6 +207,7 @@
<string name="settings_show_music_disabled_subtitle">Hide playing song info</string>
<string name="settings_song_info_format_title">Song info format</string>
<string name="settings_request_notification_access">We need the notification access permission to check the current playing song.</string>
<string name="settings_request_fitness_access">We need a few permissions to get your daily steps from Google Fit.</string>
<string name="title_googlefit" translatable="false">Google Fit</string>
<string name="settings_title_integrations">Integrations</string>
<string name="label_count_installed_integrations">%d installed integrations</string>

View File

@ -1,9 +1,5 @@
apply plugin: 'com.android.dynamic-feature'
def apiKeyPropertiesFile = rootProject.file("apikey.properties")
def apiKeyProperties = new Properties()
apiKeyProperties.load(new FileInputStream(apiKeyPropertiesFile))
android {
compileSdkVersion 29
@ -12,8 +8,6 @@ android {
targetSdkVersion 29
versionCode 1
versionName "1.0"
manifestPlaceholders = [ "AWARENESS_API_KEY": apiKeyProperties['AWARENESS_API_KEY']]
}
compileOptions {

View File

@ -11,10 +11,6 @@
<dist:on-demand />
</dist:delivery>
<dist:fusing dist:include="true" />
<meta-data
android:name="com.google.android.awareness.API_KEY"
android:value="${AWARENESS_API_KEY}"/>
</dist:module>
</manifest>

View File

@ -1,4 +1,2 @@
rootProject.name='Another Widget'
include ':app'
include ':tasksintegration'
include ':googlefit'

View File

@ -1,4 +1,4 @@
#Sat May 09 22:27:49 CEST 2020
#Sun May 10 11:42:33 CEST 2020
base.0=/Users/tommaso/Documents/MyCode/another-widget/tasksintegration/build/intermediates/dex/debug/mergeProjectDexDebug/out/classes.dex
path.0=classes.dex
renamed.0=classes.dex