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.util.Log
import android.view.View import android.view.View
import android.widget.ScrollView import android.widget.ScrollView
import androidx.core.widget.NestedScrollView
class FixedFocusScrollView @JvmOverloads constructor( class FixedFocusScrollView @JvmOverloads constructor(
context: Context, context: Context,
attrs: AttributeSet? = null, attrs: AttributeSet? = null,
defStyle: Int = 0 defStyle: Int = 0
) : ScrollView(context, attrs, defStyle) { ) : NestedScrollView(context, attrs, defStyle) {
var isScrollable = true var isScrollable = true

View File

@ -7,7 +7,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import androidx.core.app.NotificationManagerCompat 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.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.android.synthetic.main.glance_provider_settings_layout.view.* 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() { override fun show() {
val view = View.inflate(context, R.layout.glance_provider_settings_layout, null) 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.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.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.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*/ /* 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.BATTERY_LEVEL_LOW -> context.getString(R.string.settings_low_battery_level_subtitle)
Constants.GlanceProviderId.CUSTOM_INFO -> "" Constants.GlanceProviderId.CUSTOM_INFO -> ""
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_subtitle) 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 */ /* SONG */
view.action_filter_music_players.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG view.action_filter_music_players.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
view.action_filter_music_players.setOnClickListener { view.action_filter_music_players.setOnClickListener {
context.startActivity(Intent(context, MusicPlayersFilterActivity::class.java)) context.startActivity(Intent(context, MusicPlayersFilterActivity::class.java))
} }
if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
checkNotificationPermission(view) 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 view.alarm_set_by_container.isVisible = provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM
if (provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM) { if (provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM) {
view.header.text = context.getString(R.string.information_header) view.header.text = context.getString(R.string.information_header)
}
if (provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM) {
view.warning_container.isVisible = false view.warning_container.isVisible = false
checkNextAlarm(view) checkNextAlarm(view)
} }
/* GOOGLE STEPS */ /* GOOGLE STEPS */
view.action_toggle_google_fit.isVisible = provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS
if (provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS) { if (provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS) {
checkFitnessPermission(view) checkFitnessPermission(view)
} }
/* BATTERY INFO */ /* BATTERY INFO */
view.header.isVisible = provider != Constants.GlanceProviderId.BATTERY_LEVEL_LOW
if (provider == Constants.GlanceProviderId.BATTERY_LEVEL_LOW) { if (provider == Constants.GlanceProviderId.BATTERY_LEVEL_LOW) {
view.warning_container.isVisible = false view.warning_container.isVisible = false
view.header.isVisible = false
view.divider.isVisible = false view.divider.isVisible = false
} }
/* CUSTOM NOTES */ /* NOTIFICATIONS */
view.subtitle.isVisible = provider != Constants.GlanceProviderId.CUSTOM_INFO view.action_filter_notifications_app.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS
view.provider_switch.isVisible = provider != Constants.GlanceProviderId.CUSTOM_INFO 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 */ /* TOGGLE */
view.provider_switch.isChecked = when (provider) { 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.BATTERY_LEVEL_LOW -> Preferences.showBatteryCharging
Constants.GlanceProviderId.CUSTOM_INFO -> true Constants.GlanceProviderId.CUSTOM_INFO -> true
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> Preferences.showDailySteps Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> Preferences.showDailySteps
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
} }
view.provider_switch.setOnCheckedChangeListener { _, isChecked -> view.provider_switch.setOnCheckedChangeListener { _, isChecked ->
@ -112,6 +124,13 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> { Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
Preferences.showBatteryCharging = isChecked Preferences.showBatteryCharging = isChecked
} }
Constants.GlanceProviderId.NOTIFICATIONS -> {
Preferences.showNotifications = isChecked
checkLastNotificationsPermission(view)
}
Constants.GlanceProviderId.GREETINGS -> {
Preferences.showGreetings = isChecked
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> { Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (isChecked) { if (isChecked) {
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context) val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
@ -161,6 +180,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
} }
private fun checkNotificationPermission(view: View) { private fun checkNotificationPermission(view: View) {
Log.d("ciao", NotificationManagerCompat.getEnabledListenerPackages(context).toString())
when { when {
NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> { NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> {
view.warning_container.isVisible = false view.warning_container.isVisible = false
@ -172,7 +192,25 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
view.warning_container.setOnClickListener { view.warning_container.setOnClickListener {
context.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS")) 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 -> { else -> {
view.warning_container.isVisible = false 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_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_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_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"), NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"), BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
CUSTOM_INFO("CUSTOM_INFO"), CUSTOM_INFO("CUSTOM_INFO"),
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"); GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
NOTIFICATIONS("NOTIFICATIONS"),
GREETINGS("GREETINGS");
companion object { companion object {
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id) private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)

View File

@ -123,8 +123,14 @@ object Preferences : KotprefModel() {
var isCharging by booleanPref(default = false) var isCharging by booleanPref(default = false)
var googleFitSteps by longPref(default = -1) var googleFitSteps by longPref(default = -1)
var showDailySteps by booleanPref(default = false) var showDailySteps by booleanPref(default = false)
var showGreetings by booleanPref(default = false)
var showNotifications 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 showMusic by booleanPref(default = false)
var mediaInfoFormat by stringPref(default = "") var mediaInfoFormat by stringPref(default = "")
var mediaPlayerTitle by stringPref(default = "") var mediaPlayerTitle by stringPref(default = "")

View File

@ -1,19 +1,28 @@
package com.tommasoberlose.anotherwidget.helpers package com.tommasoberlose.anotherwidget.helpers
import android.app.Notification
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.util.Log import android.util.Log
import com.chibatching.kotpref.Kotpref
import com.chibatching.kotpref.blockingBulk
import com.google.gson.Gson import com.google.gson.Gson
import com.tommasoberlose.anotherwidget.global.Preferences
import java.lang.Exception
object ActiveNotificationsHelper { object ActiveNotificationsHelper {
fun getLastNotification(context: Context): StatusBarNotification? { fun showLastNotification(): Boolean {
with(context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager) { return Preferences.lastNotificationId != -1 && Preferences.lastNotificationIcon != 0 && Preferences.lastNotificationPackage.isNotBlank() && Preferences.lastNotificationTitle.isNotBlank()
activeNotifications.forEach {
Log.d("ciao", Gson().toJson(it).toString())
} }
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 package com.tommasoberlose.anotherwidget.helpers
import android.content.Context import android.content.Context
import android.util.Log
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
@ -71,6 +70,18 @@ object GlanceProviderHelper {
R.drawable.round_directions_walk 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) val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents)
&& ( && (
(Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) ||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") || (Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
(MediaPlayerHelper.isSomeonePlaying(context)) || (MediaPlayerHelper.isSomeonePlaying(context)) ||
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) || (Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
(Preferences.customNotes.isNotEmpty()) || (Preferences.customNotes.isNotEmpty()) ||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) || (Preferences.showDailySteps && Preferences.googleFitSteps > 0)
(Preferences.showNotifications && ActiveNotificationsHelper.getLastNotification(context) != null)
) )
eventRepository.close() eventRepository.close()
return showGlance return showGlance

View File

@ -222,4 +222,16 @@ object IntentHelper {
Intent() 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 package com.tommasoberlose.anotherwidget.receivers
import android.app.Notification import android.app.*
import android.media.MediaMetadata import android.content.Context
import android.media.session.MediaController import android.content.Intent
import android.media.session.MediaSession import android.media.session.MediaSession
import android.media.session.PlaybackState import android.os.Build
import android.service.notification.NotificationListenerService import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.util.Log import com.tommasoberlose.anotherwidget.global.Actions
import com.chibatching.kotpref.bulk
import com.google.gson.Gson
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import java.util.*
class NotificationListener : NotificationListenerService() { class NotificationListener : NotificationListenerService() {
@ -27,19 +26,58 @@ class NotificationListener : NotificationListenerService() {
sbn?.notification?.extras?.let { bundle -> sbn?.notification?.extras?.let { bundle ->
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let { bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
MediaPlayerHelper.updatePlayingMediaInfo(this) 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) super.onNotificationPosted(sbn)
} }
override fun onNotificationRemoved(sbn: StatusBarNotification?) { override fun onNotificationRemoved(sbn: StatusBarNotification?) {
MediaPlayerHelper.updatePlayingMediaInfo(this) MediaPlayerHelper.updatePlayingMediaInfo(this)
sbn?.let {
if (sbn.id == Preferences.lastNotificationId && sbn.packageName == Preferences.lastNotificationPackage) {
ActiveNotificationsHelper.clearLastNotification(this)
}
}
MainWidget.updateWidget(this) MainWidget.updateWidget(this)
super.onNotificationRemoved(sbn) 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.Actions
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.helpers.BatteryHelper import com.tommasoberlose.anotherwidget.helpers.BatteryHelper
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import org.joda.time.Period import org.joda.time.Period
@ -32,16 +34,24 @@ class UpdatesReceiver : BroadcastReceiver() {
Intent.ACTION_DATE_CHANGED, Intent.ACTION_DATE_CHANGED,
Actions.ACTION_CALENDAR_UPDATE -> { Actions.ACTION_CALENDAR_UPDATE -> {
CalendarHelper.updateEventList(context) CalendarHelper.updateEventList(context)
ActiveNotificationsHelper.clearLastNotification(context)
MediaPlayerHelper.updatePlayingMediaInfo(context)
} }
"com.sec.android.widgetapp.APPWIDGET_RESIZE", "com.sec.android.widgetapp.APPWIDGET_RESIZE",
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED, AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
Actions.ACTION_ALARM_UPDATE,
Actions.ACTION_TIME_UPDATE -> { Actions.ACTION_TIME_UPDATE -> {
MainWidget.updateWidget(context) MainWidget.updateWidget(context)
if (intent.hasExtra(EVENT_ID)) { if (intent.hasExtra(EVENT_ID)) {
setUpdates(context, intent.getLongExtra(EVENT_ID, -1)) 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.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.pm.PackageManager import android.graphics.Canvas
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.ViewCompat
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
@ -30,15 +27,11 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.gms.auth.api.signin.GoogleSignIn 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.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException import com.google.android.gms.common.api.ApiException
import com.karumi.dexter.Dexter import com.google.android.material.card.MaterialCardView
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.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.databinding.FragmentGlanceSettingsBinding
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences 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
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity 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.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
import com.tommasoberlose.anotherwidget.utils.toast
import kotlinx.android.synthetic.main.fragment_calendar_settings.*
import kotlinx.android.synthetic.main.fragment_glance_settings.* import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.android.synthetic.main.fragment_glance_settings.scrollView
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.idik.lib.slimadapter.SlimAdapter import net.idik.lib.slimadapter.SlimAdapter
@ -79,11 +68,14 @@ class GlanceTabFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java) 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) subscribeUi(binding, viewModel)
@ -97,8 +89,6 @@ class GlanceTabFragment : Fragment() {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
// List // List
adapter = SlimAdapter.create()
providers_list.setHasFixedSize(true) providers_list.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(context) val mLayoutManager = LinearLayoutManager(context)
providers_list.layoutManager = mLayoutManager providers_list.layoutManager = mLayoutManager
@ -130,45 +120,106 @@ class GlanceTabFragment : Fragment() {
when (provider) { when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> { Constants.GlanceProviderId.PLAYING_SONG -> {
when { when {
NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName) -> { NotificationManagerCompat.getEnabledListenerPackages(requireContext())
.contains(
requireContext().packageName) -> {
MediaPlayerHelper.updatePlayingMediaInfo(requireContext()) MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
injector.invisible(R.id.error_icon) injector.visibility(R.id.error_icon, View.GONE)
injector.text(R.id.label, if (Preferences.showMusic) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)) 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 -> { 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)) injector.text(R.id.label, getString(R.string.settings_not_visible))
} }
else -> { 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)) injector.text(R.id.label, getString(R.string.settings_not_visible))
} }
} }
} }
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> { 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.text(R.id.label,
injector.visibility(R.id.error_icon, if (Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(requireContext())) View.VISIBLE else View.GONE) 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 -> { 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.text(R.id.label,
injector.invisible(R.id.error_icon) 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 -> { 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.text(R.id.label,
injector.invisible(R.id.error_icon) 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 -> { Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION) == true) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(
injector.text(R.id.label, if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)) Manifest.permission.ACTIVITY_RECOGNITION) == true
injector.invisible(R.id.error_icon) ) {
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) { } else if (Preferences.showDailySteps) {
ActivityDetectionReceiver.unregisterFence(requireContext()) 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)) injector.text(R.id.label, getString(R.string.settings_not_visible))
} else { } else {
ActivityDetectionReceiver.unregisterFence(requireContext()) ActivityDetectionReceiver.unregisterFence(requireContext())
injector.text(R.id.label, getString(R.string.settings_not_visible)) 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, ItemTouchHelper.UP or ItemTouchHelper.DOWN,
0 0
) { ) {
val list = GlanceProviderHelper.getGlanceProviders(requireContext())
override fun onMove( override fun onMove(
recyclerView: RecyclerView, recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder,
): Boolean { ): Boolean {
val fromPos = viewHolder.adapterPosition val fromPos = viewHolder.adapterPosition
val toPos = target.adapterPosition val toPos = target.adapterPosition
// move item in `fromPos` to `toPos` in adapter. // move item in `fromPos` to `toPos` in adapter.
adapter.notifyItemMoved(fromPos, toPos) adapter.notifyItemMoved(fromPos, toPos)
val list = GlanceProviderHelper.getGlanceProviders(requireContext())
Collections.swap(list, fromPos, toPos) Collections.swap(list, fromPos, toPos)
GlanceProviderHelper.saveGlanceProviderOrder(list)
return true return true
} }
override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float { override fun isItemViewSwipeEnabled(): Boolean {
return 1f 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( override fun onSwiped(
viewHolder: RecyclerView.ViewHolder, viewHolder: RecyclerView.ViewHolder,
direction: Int direction: Int,
) { ) {
// remove from adapter // remove from adapter
} }
@ -219,14 +308,16 @@ class GlanceTabFragment : Fragment() {
private fun subscribeUi( private fun subscribeUi(
binding: FragmentGlanceSettingsBinding, binding: FragmentGlanceSettingsBinding,
viewModel: MainViewModel viewModel: MainViewModel,
) { ) {
binding.isGlanceVisible = Preferences.showGlance binding.isGlanceVisible = Preferences.showGlance
viewModel.showGlance.observe(viewLifecycleOwner, Observer { viewModel.showGlance.observe(viewLifecycleOwner, Observer {
maintainScrollPosition { maintainScrollPosition {
binding.isGlanceVisible = it 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() { private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
adapter.notifyItemChanged(1) adapter.notifyItemRangeChanged(0, adapter.data.size)
} }
} }
override fun onStart() { override fun onStart() {
super.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) { if (dialog != null) {
dialog?.show() dialog?.show()
} }
@ -263,12 +355,12 @@ class GlanceTabFragment : Fragment() {
override fun onActivityResult( override fun onActivityResult(
requestCode: Int, requestCode: Int,
resultCode: Int, resultCode: Int,
data: Intent? data: Intent?,
) { ) {
when (requestCode) { when (requestCode) {
1 -> { 1 -> {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
adapter.notifyItemChanged(2) adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) { if (dialog != null) {
dialog?.show() dialog?.show()
} }
@ -281,7 +373,8 @@ class GlanceTabFragment : Fragment() {
} }
2 -> { 2 -> {
try { 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)) { if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
GoogleSignIn.requestPermissions( GoogleSignIn.requestPermissions(
requireActivity(), requireActivity(),
@ -289,7 +382,7 @@ class GlanceTabFragment : Fragment() {
account, account,
FITNESS_OPTIONS) FITNESS_OPTIONS)
} else { } else {
adapter.notifyItemChanged(2) adapter.notifyItemRangeChanged(0, adapter.data.size)
if (dialog != null) { if (dialog != null) {
dialog?.show() 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.ColorHelper.isColorDark
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
@ -363,7 +364,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
tabs?.getTabAt(4)?.orCreateBadge?.apply { tabs?.getTabAt(4)?.orCreateBadge?.apply {
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText) backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
badgeGravity = BadgeDrawable.TOP_END 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() { override fun onResume() {

View File

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

View File

@ -7,23 +7,21 @@ import android.appwidget.AppWidgetProvider
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentSender
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.text.format.DateUtils import android.text.format.DateUtils
import android.util.Log import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
import android.view.ViewGroup import android.widget.ImageView
import android.widget.* import android.widget.RemoteViews
import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.provider.FontRequest
import androidx.core.provider.FontsContractCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.gson.Gson
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions 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.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.receivers.* 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 kotlinx.android.synthetic.main.the_widget.view.*
import java.lang.Exception
import java.text.DateFormat import java.text.DateFormat
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -348,6 +347,26 @@ class MainWidget : AppWidgetProvider() {
break@loop 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 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"/> android:textAppearance="@style/AnotherWidget.Settings.Header"/>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/providers_list" /> android:id="@+id/providers_list" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

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

View File

@ -173,6 +173,72 @@
style="@style/AnotherWidget.Settings.Subtitle"/> style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout> </LinearLayout>
</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>
</LinearLayout> </LinearLayout>
</ScrollView> </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="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_title">Ikonpakke</string>
<string name="settings_weather_icon_pack_default">Ikonpakke %d</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_api">Vejrudbyder</string>
<string name="settings_weather_provider_open_weather" translatable="false">Open Weather Map</string> <string name="settings_weather_provider_open_weather" translatable="false">Open Weather Map</string>
@ -188,7 +188,6 @@
<!-- Glance --> <!-- Glance -->
<string name="settings_show_next_alarm_title">Vis næste alarm</string> <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_at_a_glance_title">Overblik</string>
<string name="settings_show_music_title">Aktuel sang</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> <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_at_a_glance_title">Glance</string>
<string name="settings_show_music_title">Canzone in riproduzione</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_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="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="title_show_glance">Mostra At a Glance</string>
<string name="description_show_glance_visible">Informazioni visibili</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_at_a_glance_title">Glance</string>
<string name="settings_show_music_title">Current playing song</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_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="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="title_show_glance">Show at a glance info</string>
<string name="description_show_glance_visible">Service enabled</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_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_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_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 --> <!-- Settings -->
<string name="action_share">Share</string> <string name="action_share">Share</string>