Update the glance support

This commit is contained in:
Tommaso Berlose 2020-10-14 00:45:29 +02:00
parent 9f4cdc950b
commit c4a16224f0
62 changed files with 472 additions and 112 deletions

View File

@ -6,13 +6,14 @@ import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.ScrollView
import androidx.core.widget.NestedScrollView
class FixedFocusScrollView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : ScrollView(context, attrs, defStyle) {
) : NestedScrollView(context, attrs, defStyle) {
var isScrollable = true

View File

@ -7,7 +7,6 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.core.app.NotificationManagerCompat
@ -29,10 +28,9 @@ import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.android.synthetic.main.glance_provider_settings_layout.view.*
class GlanceSettingsDialog(val context: Activity, val provider: Constants.GlanceProviderId, val statusCallback: (() -> Unit)?) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
class GlanceSettingsDialog(val context: Activity, val provider: Constants.GlanceProviderId, private val statusCallback: (() -> Unit)?) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
override fun show() {
val view = View.inflate(context, R.layout.glance_provider_settings_layout, null)
@ -44,6 +42,8 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> context.getString(R.string.settings_low_battery_level_title)
Constants.GlanceProviderId.CUSTOM_INFO -> context.getString(R.string.settings_custom_notes_title)
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_title)
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
}
/* SUBTITLE*/
@ -53,14 +53,16 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> context.getString(R.string.settings_low_battery_level_subtitle)
Constants.GlanceProviderId.CUSTOM_INFO -> ""
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_subtitle)
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
}
/* SONG */
view.action_filter_music_players.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
view.action_filter_music_players.setOnClickListener {
context.startActivity(Intent(context, MusicPlayersFilterActivity::class.java))
}
if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
view.action_filter_music_players.setOnClickListener {
context.startActivity(Intent(context, MusicPlayersFilterActivity::class.java))
}
checkNotificationPermission(view)
}
@ -68,27 +70,35 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
view.alarm_set_by_container.isVisible = provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM
if (provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM) {
view.header.text = context.getString(R.string.information_header)
}
if (provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM) {
view.warning_container.isVisible = false
checkNextAlarm(view)
}
/* GOOGLE STEPS */
view.action_toggle_google_fit.isVisible = provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS
if (provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS) {
checkFitnessPermission(view)
}
/* BATTERY INFO */
view.header.isVisible = provider != Constants.GlanceProviderId.BATTERY_LEVEL_LOW
if (provider == Constants.GlanceProviderId.BATTERY_LEVEL_LOW) {
view.warning_container.isVisible = false
view.header.isVisible = false
view.divider.isVisible = false
}
/* CUSTOM NOTES */
view.subtitle.isVisible = provider != Constants.GlanceProviderId.CUSTOM_INFO
view.provider_switch.isVisible = provider != Constants.GlanceProviderId.CUSTOM_INFO
/* NOTIFICATIONS */
view.action_filter_notifications_app.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS
if (provider == Constants.GlanceProviderId.NOTIFICATIONS) {
checkLastNotificationsPermission(view)
}
/* GREETINGS */
if (provider == Constants.GlanceProviderId.GREETINGS) {
view.warning_container.isVisible = false
view.header.isVisible = false
view.divider.isVisible = false
}
/* TOGGLE */
view.provider_switch.isChecked = when (provider) {
@ -97,6 +107,8 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> Preferences.showBatteryCharging
Constants.GlanceProviderId.CUSTOM_INFO -> true
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> Preferences.showDailySteps
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
}
view.provider_switch.setOnCheckedChangeListener { _, isChecked ->
@ -112,6 +124,13 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
Preferences.showBatteryCharging = isChecked
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
Preferences.showNotifications = isChecked
checkLastNotificationsPermission(view)
}
Constants.GlanceProviderId.GREETINGS -> {
Preferences.showGreetings = isChecked
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (isChecked) {
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
@ -161,6 +180,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
}
private fun checkNotificationPermission(view: View) {
Log.d("ciao", NotificationManagerCompat.getEnabledListenerPackages(context).toString())
when {
NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> {
view.warning_container.isVisible = false
@ -172,7 +192,25 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
view.warning_container.setOnClickListener {
context.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
}
Log.d("ciao", "ok: ${view.warning_container.isVisible}")
}
else -> {
view.warning_container.isVisible = false
}
}
statusCallback?.invoke()
}
private fun checkLastNotificationsPermission(view: View) {
when {
NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> {
view.warning_container.isVisible = false
}
Preferences.showNotifications -> {
view.warning_container.isVisible = true
view.warning_title.text = context.getString(R.string.settings_request_last_notification_access)
view.warning_container.setOnClickListener {
context.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
}
}
else -> {
view.warning_container.isVisible = false

View File

@ -12,4 +12,5 @@ object Actions {
const val ACTION_GO_TO_NEXT_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_NEXT_EVENT"
const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT"
const val ACTION_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH"
const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION"
}

View File

@ -30,7 +30,9 @@ object Constants {
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
CUSTOM_INFO("CUSTOM_INFO"),
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS");
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
NOTIFICATIONS("NOTIFICATIONS"),
GREETINGS("GREETINGS");
companion object {
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)

View File

@ -123,8 +123,14 @@ object Preferences : KotprefModel() {
var isCharging by booleanPref(default = false)
var googleFitSteps by longPref(default = -1)
var showDailySteps by booleanPref(default = false)
var showGreetings by booleanPref(default = false)
var showNotifications by booleanPref(default = false)
var lastNotificationId by intPref(default = -1)
var lastNotificationTitle by stringPref(default = "")
var lastNotificationIcon by intPref(default = 0)
var lastNotificationPackage by stringPref(default = "")
var showMusic by booleanPref(default = false)
var mediaInfoFormat by stringPref(default = "")
var mediaPlayerTitle by stringPref(default = "")

View File

@ -1,19 +1,28 @@
package com.tommasoberlose.anotherwidget.helpers
import android.app.Notification
import android.app.NotificationManager
import android.content.Context
import android.service.notification.StatusBarNotification
import android.util.Log
import com.chibatching.kotpref.Kotpref
import com.chibatching.kotpref.blockingBulk
import com.google.gson.Gson
import com.tommasoberlose.anotherwidget.global.Preferences
import java.lang.Exception
object ActiveNotificationsHelper {
fun getLastNotification(context: Context): StatusBarNotification? {
with(context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager) {
activeNotifications.forEach {
Log.d("ciao", Gson().toJson(it).toString())
}
fun showLastNotification(): Boolean {
return Preferences.lastNotificationId != -1 && Preferences.lastNotificationIcon != 0 && Preferences.lastNotificationPackage.isNotBlank() && Preferences.lastNotificationTitle.isNotBlank()
}
return activeNotifications.lastOrNull()
fun clearLastNotification(context: Context) {
Kotpref.init(context)
Preferences.blockingBulk {
remove(Preferences::lastNotificationId)
remove(Preferences::lastNotificationTitle)
remove(Preferences::lastNotificationPackage)
remove(Preferences::lastNotificationIcon)
}
}
}

View File

@ -1,7 +1,6 @@
package com.tommasoberlose.anotherwidget.helpers
import android.content.Context
import android.util.Log
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Constants
@ -71,6 +70,18 @@ object GlanceProviderHelper {
R.drawable.round_directions_walk
)
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_notifications_title),
R.drawable.round_notifications
)
}
Constants.GlanceProviderId.GREETINGS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_greetings_title),
R.drawable.round_history_edu
)
}
}
}
@ -84,12 +95,12 @@ object GlanceProviderHelper {
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents)
&& (
(Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) ||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
(Preferences.customNotes.isNotEmpty()) ||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
(Preferences.showNotifications && ActiveNotificationsHelper.getLastNotification(context) != null)
(Preferences.showDailySteps && Preferences.googleFitSteps > 0)
)
eventRepository.close()
return showGlance

View File

@ -222,4 +222,16 @@ object IntentHelper {
Intent()
}
}
fun getNotificationIntent(context: Context): Intent {
val pm: PackageManager = context.packageManager
return try {
pm.getLaunchIntentForPackage(Preferences.lastNotificationPackage)!!.apply {
addCategory(Intent.CATEGORY_LAUNCHER)
}
} catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent()
}
}
}

View File

@ -1,19 +1,18 @@
package com.tommasoberlose.anotherwidget.receivers
import android.app.Notification
import android.media.MediaMetadata
import android.media.session.MediaController
import android.app.*
import android.content.Context
import android.content.Intent
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.os.Build
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import com.chibatching.kotpref.bulk
import com.google.gson.Gson
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import java.util.*
class NotificationListener : NotificationListenerService() {
@ -27,19 +26,58 @@ class NotificationListener : NotificationListenerService() {
sbn?.notification?.extras?.let { bundle ->
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
MediaPlayerHelper.updatePlayingMediaInfo(this)
} ?: run {
val isGroupHeader = sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0
val isOngoing = sbn.notification.flags and Notification.FLAG_ONGOING_EVENT != 0
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing) {
Preferences.lastNotificationId = sbn.id
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Preferences.lastNotificationIcon = sbn.notification.smallIcon.resId
Preferences.lastNotificationPackage = sbn.notification.smallIcon.resPackage
} else {
Preferences.lastNotificationIcon = sbn.notification.icon
Preferences.lastNotificationPackage = sbn.packageName
}
MainWidget.updateWidget(this)
setTimeout(this)
}
}
}
Log.d("ciao", Gson().toJson(sbn?.notification?.smallIcon))
Log.d("ciao", Gson().toJson(sbn?.notification?.contentIntent))
Log.d("ciao", Gson().toJson(sbn?.notification))
MainWidget.updateWidget(this)
super.onNotificationPosted(sbn)
}
override fun onNotificationRemoved(sbn: StatusBarNotification?) {
MediaPlayerHelper.updatePlayingMediaInfo(this)
sbn?.let {
if (sbn.id == Preferences.lastNotificationId && sbn.packageName == Preferences.lastNotificationPackage) {
ActiveNotificationsHelper.clearLastNotification(this)
}
}
MainWidget.updateWidget(this)
super.onNotificationRemoved(sbn)
}
private fun setTimeout(context: Context) {
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
val intent = Intent(context, UpdatesReceiver::class.java).apply {
action = Actions.ACTION_CLEAR_NOTIFICATION
}
cancel(PendingIntent.getBroadcast(context, 28943, intent, 0))
setExact(
AlarmManager.RTC,
Calendar.getInstance().timeInMillis + 30 * 1000,
PendingIntent.getBroadcast(
context,
5,
intent,
0
)
)
}
}
}

View File

@ -12,8 +12,10 @@ import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.helpers.BatteryHelper
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import org.joda.time.Period
@ -32,16 +34,24 @@ class UpdatesReceiver : BroadcastReceiver() {
Intent.ACTION_DATE_CHANGED,
Actions.ACTION_CALENDAR_UPDATE -> {
CalendarHelper.updateEventList(context)
ActiveNotificationsHelper.clearLastNotification(context)
MediaPlayerHelper.updatePlayingMediaInfo(context)
}
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
Actions.ACTION_ALARM_UPDATE,
Actions.ACTION_TIME_UPDATE -> {
MainWidget.updateWidget(context)
if (intent.hasExtra(EVENT_ID)) {
setUpdates(context, intent.getLongExtra(EVENT_ID, -1))
}
}
Actions.ACTION_CLEAR_NOTIFICATION -> {
ActiveNotificationsHelper.clearLastNotification(context)
MainWidget.updateWidget(context)
}
}
}

View File

@ -7,19 +7,16 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.net.Uri
import android.graphics.Canvas
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.ViewCompat
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
@ -30,15 +27,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
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.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.google.android.material.card.MaterialCardView
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.*
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
import com.tommasoberlose.anotherwidget.components.GlanceSettingsDialog
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
@ -49,14 +42,10 @@ import com.tommasoberlose.anotherwidget.models.GlanceProvider
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
import com.tommasoberlose.anotherwidget.utils.toast
import kotlinx.android.synthetic.main.fragment_calendar_settings.*
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.android.synthetic.main.fragment_glance_settings.scrollView
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.idik.lib.slimadapter.SlimAdapter
@ -79,11 +68,14 @@ class GlanceTabFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
val binding = DataBindingUtil.inflate<FragmentGlanceSettingsBinding>(inflater, R.layout.fragment_glance_settings, container, false)
val binding = DataBindingUtil.inflate<FragmentGlanceSettingsBinding>(inflater,
R.layout.fragment_glance_settings,
container,
false)
subscribeUi(binding, viewModel)
@ -97,8 +89,6 @@ class GlanceTabFragment : Fragment() {
super.onActivityCreated(savedInstanceState)
// List
adapter = SlimAdapter.create()
providers_list.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(context)
providers_list.layoutManager = mLayoutManager
@ -130,45 +120,106 @@ class GlanceTabFragment : Fragment() {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
when {
NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName) -> {
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
.contains(
requireContext().packageName) -> {
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
injector.invisible(R.id.error_icon)
injector.text(R.id.label, if (Preferences.showMusic) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
injector.text(R.id.label,
if (Preferences.showMusic) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
}
Preferences.showMusic -> {
injector.visible(R.id.error_icon)
injector.visibility(R.id.error_icon, View.VISIBLE)
injector.visibility(R.id.info_icon, View.GONE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
}
else -> {
injector.invisible(R.id.error_icon)
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
}
}
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
injector.text(R.id.label, if (Preferences.showNextAlarm && !AlarmHelper.isAlarmProbablyWrong(requireContext())) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
injector.visibility(R.id.error_icon, if (Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(requireContext())) View.VISIBLE else View.GONE)
injector.text(R.id.label,
if (Preferences.showNextAlarm && !AlarmHelper.isAlarmProbablyWrong(
requireContext())
) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
injector.visibility(R.id.error_icon,
if (Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(
requireContext())
) View.VISIBLE else View.GONE)
injector.visibility(R.id.info_icon,
if (!(Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(
requireContext()))
) View.VISIBLE else View.GONE)
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
injector.text(R.id.label, if (Preferences.showBatteryCharging) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
injector.invisible(R.id.error_icon)
injector.text(R.id.label,
if (Preferences.showBatteryCharging) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
when {
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
.contains(
requireContext().packageName) -> {
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
injector.text(R.id.label,
if (Preferences.showNotifications) getString(
R.string.settings_visible) else getString(R.string.settings_not_visible))
}
Preferences.showNotifications -> {
injector.visibility(R.id.error_icon, View.VISIBLE)
injector.visibility(R.id.info_icon, View.GONE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
}
else -> {
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
}
}
}
Constants.GlanceProviderId.GREETINGS -> {
injector.text(R.id.label,
if (Preferences.showGreetings) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
injector.text(R.id.label, if (Preferences.customNotes != "") getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
injector.invisible(R.id.error_icon)
injector.text(R.id.label,
if (Preferences.customNotes != "") getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION) == true) {
injector.text(R.id.label, if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
injector.invisible(R.id.error_icon)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(
Manifest.permission.ACTIVITY_RECOGNITION) == true
) {
injector.text(R.id.label,
if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
} else if (Preferences.showDailySteps) {
ActivityDetectionReceiver.unregisterFence(requireContext())
injector.visible(R.id.error_icon)
injector.visibility(R.id.error_icon, View.VISIBLE)
injector.visibility(R.id.info_icon, View.GONE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
} else {
ActivityDetectionReceiver.unregisterFence(requireContext())
injector.text(R.id.label, getString(R.string.settings_not_visible))
injector.invisible(R.id.error_icon)
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
}
}
}
@ -180,28 +231,66 @@ class GlanceTabFragment : Fragment() {
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
0
) {
val list = GlanceProviderHelper.getGlanceProviders(requireContext())
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder,
): Boolean {
val fromPos = viewHolder.adapterPosition
val toPos = target.adapterPosition
// move item in `fromPos` to `toPos` in adapter.
adapter.notifyItemMoved(fromPos, toPos)
val list = GlanceProviderHelper.getGlanceProviders(requireContext())
Collections.swap(list, fromPos, toPos)
GlanceProviderHelper.saveGlanceProviderOrder(list)
return true
}
override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float {
return 1f
override fun isItemViewSwipeEnabled(): Boolean {
return false
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
GlanceProviderHelper.saveGlanceProviderOrder(list)
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean,
) {
val view = viewHolder.itemView as MaterialCardView
if (isCurrentlyActive) {
ViewCompat.setElevation(view, 2f.convertDpToPixel(requireContext()))
view.setCardBackgroundColor(ContextCompat.getColor(requireContext(),
R.color.colorPrimary))
} else {
ViewCompat.setElevation(view, 0f)
view.setCardBackgroundColor(ContextCompat.getColor(requireContext(),
R.color.colorPrimaryDark))
}
super.onChildDraw(c,
recyclerView,
viewHolder,
dX,
dY,
actionState,
isCurrentlyActive)
}
override fun onSwiped(
viewHolder: RecyclerView.ViewHolder,
direction: Int
direction: Int,
) {
// remove from adapter
}
@ -219,14 +308,16 @@ class GlanceTabFragment : Fragment() {
private fun subscribeUi(
binding: FragmentGlanceSettingsBinding,
viewModel: MainViewModel
viewModel: MainViewModel,
) {
binding.isGlanceVisible = Preferences.showGlance
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
binding.isGlanceVisible = it
show_glance_label.text = if (it) getString(R.string.description_show_glance_visible) else getString(R.string.description_show_glance_not_visible)
show_glance_label.text =
if (it) getString(R.string.description_show_glance_visible) else getString(
R.string.description_show_glance_not_visible)
}
})
}
@ -243,13 +334,14 @@ class GlanceTabFragment : Fragment() {
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
adapter.notifyItemChanged(1)
adapter.notifyItemRangeChanged(0, adapter.data.size)
}
}
override fun onStart() {
super.onStart()
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver,
IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
if (dialog != null) {
dialog?.show()
}
@ -263,12 +355,12 @@ class GlanceTabFragment : Fragment() {
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
data: Intent?,
) {
when (requestCode) {
1 -> {
if (resultCode == Activity.RESULT_OK) {
adapter.notifyItemChanged(2)
adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) {
dialog?.show()
}
@ -279,9 +371,10 @@ class GlanceTabFragment : Fragment() {
}
}
}
2-> {
2 -> {
try {
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(data).getResult(ApiException::class.java)
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(
data).getResult(ApiException::class.java)
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
GoogleSignIn.requestPermissions(
requireActivity(),
@ -289,7 +382,7 @@ class GlanceTabFragment : Fragment() {
account,
FITNESS_OPTIONS)
} else {
adapter.notifyItemChanged(2)
adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) {
dialog?.show()
}

View File

@ -35,6 +35,7 @@ import com.tommasoberlose.anotherwidget.helpers.ColorHelper
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
@ -363,7 +364,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
tabs?.getTabAt(4)?.orCreateBadge?.apply {
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
badgeGravity = BadgeDrawable.TOP_END
}?.isVisible = Preferences.showMusic && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)
}?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)) ||
(Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION)))
}
override fun onResume() {

View File

@ -26,6 +26,7 @@ import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.databinding.FragmentSettingsBinding
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
@ -131,9 +132,6 @@ class SettingsFragment : Fragment() {
Preferences.showPreview = isChecked
}
action_show_wallpaper.setOnClickListener {
}
action_show_wallpaper.setOnClickListener {
show_wallpaper_toggle.isChecked = !show_wallpaper_toggle.isChecked
}
@ -198,6 +196,7 @@ class SettingsFragment : Fragment() {
}
CalendarHelper.updateEventList(requireContext())
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
ActiveNotificationsHelper.clearLastNotification(requireContext())
}
}

View File

@ -7,23 +7,21 @@ import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.IntentSender
import android.content.res.Resources
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.text.format.DateUtils
import android.util.Log
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.*
import android.widget.ImageView
import android.widget.RemoteViews
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.provider.FontRequest
import androidx.core.provider.FontsContractCompat
import androidx.core.view.isVisible
import com.google.gson.Gson
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions
@ -32,9 +30,10 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.receivers.*
import com.tommasoberlose.anotherwidget.utils.*
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.toPixel
import kotlinx.android.synthetic.main.the_widget.view.*
import java.lang.Exception
import java.text.DateFormat
import java.util.*
import java.util.concurrent.TimeUnit
@ -348,6 +347,26 @@ class MainWidget : AppWidgetProvider() {
break@loop
}
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try {
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
val icon = ContextCompat.getDrawable(remotePackageContext, Preferences.lastNotificationIcon)
val notificationIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getNotificationIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(
R.id.second_row_rect,
notificationIntent
)
showSomething = true
break@loop
} catch (ex: Exception) {}
}
}
}
}
@ -695,6 +714,19 @@ class MainWidget : AppWidgetProvider() {
break@loop
}
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try {
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
val icon = ContextCompat.getDrawable(remotePackageContext, Preferences.lastNotificationIcon)
v.second_row_icon.isVisible = true
v.second_row_icon.setImageDrawable(icon)
v.next_event_date.text = Preferences.lastNotificationTitle
showSomething = true
break@loop
} catch (ex: Exception) {}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M9,5v0.38c-0.83,-0.33 -1.72,-0.5 -2.61,-0.5c-1.42,0 -2.84,0.43 -4.05,1.29C1.83,6.53 1.77,7.26 2.21,7.7l2.57,2.57h1.11v1.11c0.86,0.86 1.98,1.31 3.11,1.36V15H7c-0.55,0 -1,0.45 -1,1v2c0,1.1 0.9,2 2,2h10c1.66,0 3,-1.34 3,-3V5c0,-0.55 -0.45,-1 -1,-1H10C9.45,4 9,4.45 9,5zM7.89,10.41V8.26H5.61L4.57,7.22C5.14,7 5.76,6.88 6.39,6.88c1.34,0 2.59,0.52 3.54,1.46l1.41,1.41l-0.2,0.2c-0.51,0.51 -1.19,0.8 -1.92,0.8C8.75,10.75 8.29,10.63 7.89,10.41zM19,17c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1v-1c0,-0.55 -0.45,-1 -1,-1h-5v-2.59c0.57,-0.23 1.1,-0.57 1.56,-1.03l0.2,-0.2L15.59,14H17v-1.41l-6,-5.97V6h8V17z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-1.29,1.29c-0.63,0.63 -0.19,1.71 0.7,1.71h13.17c0.89,0 1.34,-1.08 0.71,-1.71L18,16z"/>
</vector>

View File

@ -96,7 +96,8 @@
android:textAppearance="@style/AnotherWidget.Settings.Header"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/providers_list" />
<LinearLayout
android:layout_width="match_parent"

View File

@ -7,28 +7,33 @@
android:clickable="true"
android:focusable="true"
app:cardElevation="0dp"
android:id="@+id/item"
android:foreground="?android:attr/selectableItemBackground"
app:cardBackgroundColor="@color/colorPrimaryDark"
app:cardCornerRadius="3dp">
app:cardCornerRadius="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/item"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="11dp"
android:id="@+id/icon"
android:visibility="gone"
android:src="@drawable/round_music_note"
app:tint="@color/colorPrimaryText"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="11dp"
android:src="@drawable/round_drag"
app:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
@ -51,9 +56,18 @@
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:padding="10dp"
android:src="@drawable/round_error"
app:tint="@color/errorColorText"
android:id="@+id/error_icon"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="10dp"
android:id="@+id/info_icon"
android:src="@drawable/round_arrow_circle_down"
android:rotation="-90"
android:alpha="0.8"
app:tint="@color/colorPrimaryText"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -173,6 +173,72 @@
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="24dp"
android:paddingRight="24dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_filter_notifications_app"
android:orientation="horizontal">
<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"
android:textSize="16sp"
style="@style/AnotherWidget.Settings.Title"
android:text="App notifications filter"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/settings_music_players_filter_subtitle"
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="24dp"
android:paddingRight="24dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_toggle_google_fit"
android:orientation="horizontal">
<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"
android:textSize="16sp"
style="@style/AnotherWidget.Settings.Title"
android:text="Google Fit"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/settings_music_players_filter_subtitle"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -127,7 +127,7 @@
<string name="api_key_info_all_set">Der kan gå op til 10 minutter inden din API nøgle er aktiveret. Vejret vil blive opdateret så snart det er tilgængeligt.</string>
<string name="settings_weather_icon_pack_title">Ikonpakke</string>
<string name="settings_weather_icon_pack_default">Ikonpakke %d</string>
<string name="background_location_warning">Vi indsamler placeringsdata for at opdatere vejrinformationer, selv når app'en er lukket eller ikke er i brug.\nVi bruger ikke disse data på andre måder.</string>
<string name="background_location_warning">Vi indsamler placeringsdata for at opdatere vejrinformationer, selv når app\'en er lukket eller ikke er i brug.\nVi bruger ikke disse data på andre måder.</string>
<string name="settings_weather_provider_api">Vejrudbyder</string>
<string name="settings_weather_provider_open_weather" translatable="false">Open Weather Map</string>
@ -188,7 +188,6 @@
<!-- Glance -->
<string name="settings_show_next_alarm_title">Vis næste alarm</string>
<string name="next_alarm_warning">Den næste alarm lader til at være forkert.\nDen er indstillet af %s.</string>
<string name="settings_at_a_glance_title">Overblik</string>
<string name="settings_show_music_title">Aktuel sang</string>
<string name="settings_request_notification_access">Vi har brug for tilladelse til aflæsning af notifikationer, for at vise den aktuelle sang.</string>

View File

@ -179,6 +179,7 @@
<string name="settings_at_a_glance_title">Glance</string>
<string name="settings_show_music_title">Canzone in riproduzione</string>
<string name="settings_request_notification_access">È necessario l\'accesso alle notifiche per controllare la canzone in riproduzione.</string>
<string name="settings_request_last_notification_access">È necessario l\'accesso alle notifiche per mostrare le ultime che ti sono arrivate.</string>
<string name="settings_request_fitness_access">Sono necessari i permessi per accedere ai passi di oggi su Google Fit.</string>
<string name="title_show_glance">Mostra At a Glance</string>
<string name="description_show_glance_visible">Informazioni visibili</string>

View File

@ -191,6 +191,7 @@
<string name="settings_at_a_glance_title">Glance</string>
<string name="settings_show_music_title">Current playing song</string>
<string name="settings_request_notification_access">We need the notification access permission to check the current playing song.</string>
<string name="settings_request_last_notification_access">We need the notification access permission to check your last notifications.</string>
<string name="settings_request_fitness_access">We need a few permissions to get your daily steps from Google Fit.</string>
<string name="title_show_glance">Show at a glance info</string>
<string name="description_show_glance_visible">Service enabled</string>
@ -215,6 +216,10 @@
<string name="settings_show_next_alarm_app_title">Alarm set by %s</string>
<string name="settings_show_next_alarm_app_subtitle_wrong">The next alarm clock seems to be wrong.</string>
<string name="settings_show_next_alarm_app_subtitle_correct">The next alarm clock seems to be correct.</string>
<string name="settings_show_notifications_title">Last notifications</string>
<string name="settings_show_notifications_subtitle">Take a quick view of the last notifications showed up on your device.</string>
<string name="settings_show_greetings_title">Greetings</string>
<string name="settings_show_greetings_subtitle">View some cool phrase when you don\'t expect it.</string>
<!-- Settings -->
<string name="action_share">Share</string>