From 1c1f55e20aee30eae497ef718befd76e0dd6079d Mon Sep 17 00:00:00 2001 From: Tommaso Berlose Date: Wed, 14 Oct 2020 12:54:39 +0200 Subject: [PATCH] Add the app notifications filter --- .idea/caches/build_file_checksums.ser | Bin 537 -> 537 bytes app/build.gradle | 20 +-- app/src/main/AndroidManifest.xml | 1 + .../components/GlanceSettingsDialog.kt | 9 +- .../anotherwidget/global/Preferences.kt | 1 + .../helpers/ActiveNotificationsHelper.kt | 27 +++- .../helpers/MediaPlayerHelper.kt | 7 +- .../receivers/NotificationListener.kt | 3 +- .../AppNotificationsFilterActivity.kt | 143 ++++++++++++++++++ .../activities/MusicPlayersFilterActivity.kt | 2 +- .../ui/fragments/GlanceTabFragment.kt | 10 +- .../ui/fragments/MainFragment.kt | 17 ++- .../viewmodels/AppNotificationsViewModel.kt | 39 +++++ .../activity_app_notifications_filter.xml | 123 +++++++++++++++ .../layout/activity_music_players_filter.xml | 3 + .../glance_provider_settings_layout.xml | 4 +- app/src/main/res/values-it/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + gradle/wrapper/gradle-wrapper.properties | 4 +- 19 files changed, 376 insertions(+), 41 deletions(-) create mode 100644 app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/AppNotificationsFilterActivity.kt create mode 100644 app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/AppNotificationsViewModel.kt create mode 100644 app/src/main/res/layout/activity_app_notifications_filter.xml diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 8b8b75a930413308aa87fc9b39deeace5d69f624..803aa89655d7b67d0e4e9adcd9e25833dcc4aec1 100644 GIT binary patch delta 33 rcmV++0N($Z1epYom;@%hz?rd}YylB5P$WfUi>nEzG$Y5~z-#(=-VhEv delta 33 rcmV++0N($Z1epYom;@mJ5b?2`YylC{NYJ{GuAOW|xf?6&3;*?a;7JbV diff --git a/app/build.gradle b/app/build.gradle index 023be3a..88e12e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,8 +23,8 @@ android { applicationId "com.tommasoberlose.anotherwidget" minSdkVersion 23 targetSdkVersion 29 - versionCode 106 - versionName "2.0.14" + versionCode 107 + versionName "2.0.15" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY']) @@ -64,13 +64,13 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.legacy:legacy-support-v4:1.0.0' - testImplementation 'junit:junit:4.13' + testImplementation 'junit:junit:4.13.1' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' // UI implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' implementation 'com.google.android.material:material:1.3.0-alpha03' implementation 'androidx.browser:browser:1.2.0' implementation 'net.idik:slimadapter:2.1.2' @@ -84,15 +84,15 @@ dependencies { implementation "androidx.work:work-runtime-ktx:2.4.0" // EventBus - implementation 'org.greenrobot:eventbus:3.1.1' + implementation 'org.greenrobot:eventbus:3.2.0' // Navigation - implementation 'androidx.navigation:navigation-fragment:2.3.0' + implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0' implementation 'androidx.navigation:navigation-ui-ktx:2.3.0' // Other implementation 'androidx.multidex:multidex:2.0.1' - implementation 'joda-time:joda-time:2.10.3' + implementation 'joda-time:joda-time:2.10.6' implementation 'me.everything:providers-android:1.0.1' implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2' @@ -121,8 +121,8 @@ dependencies { //Retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.google.code.gson:gson:2.8.6' - implementation 'com.squareup.retrofit2:converter-gson:2.8.1' - implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0' + implementation 'com.squareup.retrofit2:converter-gson:2.9.0' + implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0' implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1" //Coroutines @@ -137,7 +137,7 @@ dependencies { implementation 'androidx.preference:preference-ktx:1.1.1' // Permissions - implementation 'com.karumi:dexter:6.1.0' + implementation 'com.karumi:dexter:6.2.1' // Fonts implementation 'com.github.firatkarababa:downloadable-font-list-library:1.0.2' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ed5a2ee..2a0fd53 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,6 +40,7 @@ + diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt index 4ea2338..acf5020 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt @@ -23,9 +23,11 @@ import com.karumi.dexter.listener.multi.MultiplePermissionsListener import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Preferences +import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper import com.tommasoberlose.anotherwidget.helpers.AlarmHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver +import com.tommasoberlose.anotherwidget.ui.activities.AppNotificationsFilterActivity import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import kotlinx.android.synthetic.main.glance_provider_settings_layout.view.* @@ -94,6 +96,9 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance view.action_filter_notifications_app.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS if (provider == Constants.GlanceProviderId.NOTIFICATIONS) { checkLastNotificationsPermission(view) + view.action_filter_notifications_app.setOnClickListener { + context.startActivity(Intent(context, AppNotificationsFilterActivity::class.java)) + } } /* GREETINGS */ @@ -200,7 +205,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance private fun checkNotificationPermission(view: View) { when { - NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> { + ActiveNotificationsHelper.checkNotificationAccess(context) -> { view.warning_container.isVisible = false MediaPlayerHelper.updatePlayingMediaInfo(context) } @@ -220,7 +225,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance private fun checkLastNotificationsPermission(view: View) { when { - NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) -> { + ActiveNotificationsHelper.checkNotificationAccess(context) -> { view.warning_container.isVisible = false } Preferences.showNotifications -> { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt index b4c72b1..e1bffbf 100755 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt @@ -138,6 +138,7 @@ object Preferences : KotprefModel() { var mediaPlayerArtist by stringPref(default = "") var mediaPlayerPackage by stringPref(default = "") var musicPlayersFilter by stringPref(default = "") + var appNotificationsFilter by stringPref(default = "") // Integrations var installedIntegrations by intPref(default = 0) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/ActiveNotificationsHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/ActiveNotificationsHelper.kt index f07a049..c11f779 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/ActiveNotificationsHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/ActiveNotificationsHelper.kt @@ -1,15 +1,14 @@ package com.tommasoberlose.anotherwidget.helpers -import android.app.Notification -import android.app.NotificationManager +import android.content.ContentResolver import android.content.Context -import android.service.notification.StatusBarNotification +import android.provider.Settings import android.util.Log +import androidx.core.app.NotificationManagerCompat 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 +import com.tommasoberlose.anotherwidget.receivers.NotificationListener object ActiveNotificationsHelper { fun showLastNotification(): Boolean { @@ -25,4 +24,22 @@ object ActiveNotificationsHelper { remove(Preferences::lastNotificationIcon) } } + + fun checkNotificationAccess(context: Context): Boolean { + val contentResolver: ContentResolver = context.contentResolver + val enabledNotificationListeners = + Settings.Secure.getString(contentResolver, "enabled_notification_listeners") + val packageName: String = context.packageName + return NotificationManagerCompat.getEnabledListenerPackages(context).contains(packageName) && (enabledNotificationListeners != null && enabledNotificationListeners.contains(NotificationListener::class.java.name)) + } + + fun isAppAccepted(appPkg: String): Boolean = Preferences.appNotificationsFilter == "" || Preferences.appNotificationsFilter.contains(appPkg) + + fun toggleAppFilter(appPkg: String) { + if (Preferences.appNotificationsFilter == "" || !Preferences.appNotificationsFilter.contains(appPkg)) { + Preferences.appNotificationsFilter = Preferences.appNotificationsFilter.split(",").union(listOf(appPkg)).joinToString(separator = ",") + } else { + Preferences.appNotificationsFilter = Preferences.appNotificationsFilter.split(",").filter { it != appPkg }.joinToString(separator = ",") + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/MediaPlayerHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/MediaPlayerHelper.kt index 1b63b19..d90cb45 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/MediaPlayerHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/MediaPlayerHelper.kt @@ -6,7 +6,6 @@ import android.media.MediaMetadata import android.media.session.MediaController import android.media.session.MediaSessionManager import android.media.session.PlaybackState -import androidx.core.app.NotificationManagerCompat import com.chibatching.kotpref.Kotpref import com.chibatching.kotpref.blockingBulk import com.chibatching.kotpref.bulk @@ -16,7 +15,7 @@ import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import java.lang.Exception object MediaPlayerHelper { - fun isSomeonePlaying(context: Context) = Preferences.showMusic && NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) && Preferences.mediaPlayerTitle != "" + fun isSomeonePlaying(context: Context) = Preferences.showMusic && ActiveNotificationsHelper.checkNotificationAccess(context) && Preferences.mediaPlayerTitle != "" fun getMediaInfo(): String { return if (Preferences.mediaPlayerArtist == "") { @@ -28,7 +27,7 @@ object MediaPlayerHelper { fun updatePlayingMediaInfo(context: Context) { Kotpref.init(context) - if (NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName)) { + if (ActiveNotificationsHelper.checkNotificationAccess(context)) { val list = try { (context.getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager).getActiveSessions( ComponentName(context.packageName, NotificationListener::class.java.name) @@ -89,7 +88,7 @@ object MediaPlayerHelper { } } - fun isMusicPlayerAccepted(appPkg: String): Boolean = Preferences.musicPlayersFilter.contains(appPkg) + fun isMusicPlayerAccepted(appPkg: String): Boolean = Preferences.musicPlayersFilter == "" || Preferences.musicPlayersFilter.contains(appPkg) fun toggleMusicPlayerFilter(appPkg: String) { if (Preferences.musicPlayersFilter == "" || !Preferences.musicPlayersFilter.contains(appPkg)) { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt index 57227aa..95187b9 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt @@ -7,6 +7,7 @@ import android.media.session.MediaSession import android.os.Build import android.service.notification.NotificationListenerService import android.service.notification.StatusBarNotification +import android.util.Log import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper @@ -30,7 +31,7 @@ class NotificationListener : NotificationListenerService() { 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) { + if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName)) { Preferences.lastNotificationId = sbn.id Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: "" if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/AppNotificationsFilterActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/AppNotificationsFilterActivity.kt new file mode 100644 index 0000000..f7b47e3 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/AppNotificationsFilterActivity.kt @@ -0,0 +1,143 @@ +package com.tommasoberlose.anotherwidget.ui.activities + +import android.content.pm.ResolveInfo +import android.os.Bundle +import android.view.View +import android.widget.ImageView +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.isVisible +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.LinearLayoutManager +import com.bumptech.glide.Glide +import com.tommasoberlose.anotherwidget.R +import com.tommasoberlose.anotherwidget.databinding.ActivityAppNotificationsFilterBinding +import com.tommasoberlose.anotherwidget.global.Preferences +import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper +import com.tommasoberlose.anotherwidget.ui.viewmodels.AppNotificationsViewModel +import kotlinx.android.synthetic.main.activity_app_notifications_filter.* +import kotlinx.coroutines.* +import net.idik.lib.slimadapter.SlimAdapter + + +class AppNotificationsFilterActivity : AppCompatActivity() { + + private lateinit var adapter: SlimAdapter + private lateinit var viewModel: AppNotificationsViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + viewModel = ViewModelProvider(this).get(AppNotificationsViewModel::class.java) + val binding = DataBindingUtil.setContentView(this, R.layout.activity_app_notifications_filter) + + list_view.setHasFixedSize(true) + val mLayoutManager = LinearLayoutManager(this) + list_view.layoutManager = mLayoutManager + + adapter = SlimAdapter.create() + adapter + .register(R.layout.application_info_layout) { item, injector -> + injector + .text(R.id.text, item.loadLabel(viewModel.pm)) + .with(R.id.icon) { + Glide + .with(this) + .load(item.loadIcon(viewModel.pm)) + .centerCrop() + .into(it) + } + .visible(R.id.checkBox) + .clicked(R.id.item) { + toggleApp(item) + adapter.notifyItemRangeChanged(0, adapter.data.size) + } + .clicked(R.id.checkBox) { + toggleApp(item) + adapter.notifyItemRangeChanged(0, adapter.data.size) + } + .checked(R.id.checkBox, ActiveNotificationsHelper.isAppAccepted(item.activityInfo.packageName)) + } + .attachTo(list_view) + + setupListener() + subscribeUi(binding, viewModel) + + search.requestFocus() + } + + private var filterJob: Job? = null + + private fun subscribeUi(binding: ActivityAppNotificationsFilterBinding, viewModel: AppNotificationsViewModel) { + binding.viewModel = viewModel + binding.lifecycleOwner = this + + viewModel.appList.observe(this, Observer { + updateList(list = it) + loader.visibility = View.INVISIBLE + }) + + viewModel.searchInput.observe(this, Observer { search -> + updateList(search = search) + clear_search.isVisible = search.isNotBlank() + }) + + viewModel.appNotificationsFilter.observe(this, { + updateList() + clear_selection.isVisible = Preferences.appNotificationsFilter != "" + }) + } + + private fun updateList(list: List? = viewModel.appList.value, search: String? = viewModel.searchInput.value) { + loader.visibility = View.VISIBLE + filterJob?.cancel() + filterJob = lifecycleScope.launch(Dispatchers.IO) { + if (list != null && list.isNotEmpty()) { + delay(200) + val filteredList: List = if (search == null || search == "") { + list + } else { + list.filter { + it.loadLabel(viewModel.pm).contains(search, true) + } + }.sortedWith { app1, app2 -> + if (ActiveNotificationsHelper.isAppAccepted(app1.activityInfo.packageName) && ActiveNotificationsHelper.isAppAccepted(app2.activityInfo.packageName)) { + app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true) + } else if (ActiveNotificationsHelper.isAppAccepted(app1.activityInfo.packageName)) { + -1 + } else if (ActiveNotificationsHelper.isAppAccepted(app2.activityInfo.packageName)) { + 1 + } else { + app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true) + } + } + + + withContext(Dispatchers.Main) { + adapter.updateData(filteredList) + loader.visibility = View.INVISIBLE + } + } + } + } + + private fun setupListener() { + action_back.setOnClickListener { + onBackPressed() + } + + clear_search.setOnClickListener { + viewModel.searchInput.value = "" + } + + clear_selection.setOnClickListener { + Preferences.appNotificationsFilter = "" + } + } + + private fun toggleApp(app: ResolveInfo) { + ActiveNotificationsHelper.toggleAppFilter(app.activityInfo.packageName) + } +} diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MusicPlayersFilterActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MusicPlayersFilterActivity.kt index 28e7f81..495a659 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MusicPlayersFilterActivity.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MusicPlayersFilterActivity.kt @@ -142,7 +142,7 @@ class MusicPlayersFilterActivity : AppCompatActivity() { } clear_selection.setOnClickListener { - Preferences.musicPlayersFilter = "," + Preferences.musicPlayersFilter = "" } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt index 740daee..0b11ebb 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/GlanceTabFragment.kt @@ -36,6 +36,7 @@ import com.tommasoberlose.anotherwidget.components.GlanceSettingsDialog import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Preferences +import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper import com.tommasoberlose.anotherwidget.helpers.AlarmHelper import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper @@ -121,9 +122,7 @@ class GlanceTabFragment : Fragment() { when (provider) { Constants.GlanceProviderId.PLAYING_SONG -> { when { - NotificationManagerCompat.getEnabledListenerPackages(requireContext()) - .contains( - requireContext().packageName) -> { + ActiveNotificationsHelper.checkNotificationAccess(requireContext()) -> { MediaPlayerHelper.updatePlayingMediaInfo(requireContext()) injector.visibility(R.id.error_icon, View.GONE) injector.visibility(R.id.info_icon, View.VISIBLE) @@ -167,9 +166,7 @@ class GlanceTabFragment : Fragment() { } Constants.GlanceProviderId.NOTIFICATIONS -> { when { - NotificationManagerCompat.getEnabledListenerPackages(requireContext()) - .contains( - requireContext().packageName) -> { + ActiveNotificationsHelper.checkNotificationAccess(requireContext()) -> { injector.visibility(R.id.error_icon, View.GONE) injector.visibility(R.id.info_icon, View.VISIBLE) injector.text(R.id.label, @@ -305,6 +302,7 @@ class GlanceTabFragment : Fragment() { adapter.updateData( GlanceProviderHelper.getGlanceProviders(requireContext()) .mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) } + .filterNot { it.id == Constants.GlanceProviderId.GREETINGS.id } ) providers_list.isNestedScrollingEnabled = false diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt index 60f2d51..d885c76 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt @@ -72,8 +72,6 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - subscribeUi(viewModel) - // Viewpager pager.adapter = ViewPagerAdapter(requireActivity()) pager.offscreenPageLimit = 4 @@ -89,17 +87,20 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList }.attach() // Init clock - time.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true)) - time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext())) - time_am_pm.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true)) - time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2) + if (Preferences.showClock) { + time.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true)) + time.setTextSize(TypedValue.COMPLEX_UNIT_SP, + Preferences.clockTextSize.toPixel(requireContext())) + time_am_pm.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true)) + time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP, + Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2) + } time_container.isVisible = Preferences.showClock preview.layoutParams = preview.layoutParams.apply { height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0 } subscribeUi(viewModel) - updateUI() // Warnings if (getString(R.string.xiaomi_manufacturer).equals(Build.MANUFACTURER, ignoreCase = true) && Preferences.showXiaomiWarning) { @@ -361,7 +362,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList tabs?.getTabAt(4)?.orCreateBadge?.apply { backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText) badgeGravity = BadgeDrawable.TOP_END - }?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)) || + }?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !ActiveNotificationsHelper.checkNotificationAccess(requireContext())) || (Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION))) || (AlarmHelper.isAlarmProbablyWrong(requireContext())) } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/AppNotificationsViewModel.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/AppNotificationsViewModel.kt new file mode 100644 index 0000000..c41312a --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/AppNotificationsViewModel.kt @@ -0,0 +1,39 @@ +package com.tommasoberlose.anotherwidget.ui.viewmodels + +import android.app.Application +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.chibatching.kotpref.livedata.asLiveData +import com.tommasoberlose.anotherwidget.global.Preferences +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + + +class AppNotificationsViewModel(application: Application) : AndroidViewModel(application) { + + val pm: PackageManager by lazy { application.packageManager } + val appList: MutableLiveData> = MutableLiveData() + val searchInput: MutableLiveData = MutableLiveData("") + var appNotificationsFilter = Preferences.asLiveData(Preferences::appNotificationsFilter) + + init { + viewModelScope.launch(Dispatchers.IO) { + val mainIntent = Intent(Intent.ACTION_MAIN, null).apply { + addCategory(Intent.CATEGORY_LAUNCHER) + } + + val app = application.packageManager.queryIntentActivities(mainIntent, 0) + val sortedApp = app.sortedWith(Comparator { app1: ResolveInfo, app2: ResolveInfo -> + app1.loadLabel(pm).toString().compareTo(app2.loadLabel(pm).toString()) + }) + withContext(Dispatchers.Main) { + appList.postValue(sortedApp) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_app_notifications_filter.xml b/app/src/main/res/layout/activity_app_notifications_filter.xml new file mode 100644 index 0000000..4ee61a3 --- /dev/null +++ b/app/src/main/res/layout/activity_app_notifications_filter.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_music_players_filter.xml b/app/src/main/res/layout/activity_music_players_filter.xml index e0628de..18378ca 100644 --- a/app/src/main/res/layout/activity_music_players_filter.xml +++ b/app/src/main/res/layout/activity_music_players_filter.xml @@ -49,6 +49,9 @@ android:layout_width="48dp" android:layout_height="48dp" android:padding="12dp" + android:clickable="true" + android:focusable="true" + android:background="?attr/selectableItemBackgroundBorderless" android:src="@drawable/round_clear_all" app:tint="@color/colorPrimaryText" android:layout_alignParentRight="true" diff --git a/app/src/main/res/layout/glance_provider_settings_layout.xml b/app/src/main/res/layout/glance_provider_settings_layout.xml index 5e57c41..6b114f7 100644 --- a/app/src/main/res/layout/glance_provider_settings_layout.xml +++ b/app/src/main/res/layout/glance_provider_settings_layout.xml @@ -197,12 +197,12 @@ android:layout_height="wrap_content" android:textSize="16sp" style="@style/AnotherWidget.Settings.Title" - android:text="App notifications filter"/> + android:text="@string/applications_filter_title"/> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 761a19c..6c08f2c 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -209,6 +209,8 @@ Google Fit Collega Scollega + Applicazioni + Scegli le notifiche che vuoi vedere Condividi diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 60cfdfb..967ca7c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -226,6 +226,8 @@ Google Fit Connect Disconnect + Applications + Choose which notifications to view Share diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8b3104a..6257923 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Oct 13 10:06:21 CEST 2020 +#Wed Oct 14 12:52:53 CEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip