Loading app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt +1 −7 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ import foundation.e.advancedprivacy.domain.usecases.ShowFeaturesWarningUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStateUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase import foundation.e.advancedprivacy.domain.usecases.VpnSupervisorUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule import foundation.e.advancedprivacy.externalinterfaces.workers.WeeklyReportWorker import foundation.e.advancedprivacy.trackers.services.UpdateTrackersWorker import foundation.e.lib.telemetry.Telemetry Loading Loading @@ -64,12 +63,7 @@ class AdvancedPrivacyApplication : Application() { get(TrackersStatisticsUseCase::class.java) ) Notifications.startListening( this, get(GetQuickPrivacyStateUseCase::class.java), get(IPermissionsPrivacyModule::class.java), get(CoroutineScope::class.java) ) get<NotificationsPresenter>(NotificationsPresenter::class.java).startListening() get<IpScramblingStateUseCase>(IpScramblingStateUseCase::class.java) get<TrackersStateUseCase>(TrackersStateUseCase::class.java) Loading app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +11 −0 Original line number Diff line number Diff line Loading @@ -229,4 +229,15 @@ val appModule = module { viewModelOf(::DashboardViewModel) single { WeeklyReportViewFactory() } single { NotificationsPresenter( context = androidContext(), getQuickPrivacyStateUseCase = get(), permissionsPrivacyModule = get(), weeklyReportUseCase = get(), weeklyReportViewFactory = get(), appScope = get() ) } } app/src/main/java/foundation/e/advancedprivacy/Notifications.kt→app/src/main/java/foundation/e/advancedprivacy/NotificationsPresenter.kt +82 −38 Original line number Diff line number Diff line /* * Copyright (C) 2024 E FOUNDATION * Copyright (C) 2024 - 2025 E FOUNDATION * Copyright (C) 2022 - 2023 MURENA SAS * * This program is free software: you can redistribute it and/or modify Loading @@ -24,29 +24,47 @@ import android.content.Context import androidx.annotation.StringRes import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat import foundation.e.advancedprivacy.core.utils.notificationBuilder import foundation.e.advancedprivacy.domain.entities.CHANNEL_FAKE_LOCATION_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_FIRST_BOOT import foundation.e.advancedprivacy.domain.entities.CHANNEL_IPSCRAMBLING_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_TRACKER_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_WEEKLYREPORT import foundation.e.advancedprivacy.domain.entities.FeatureMode import foundation.e.advancedprivacy.domain.entities.FeatureState import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FAKE_LOCATION_FLAG import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FIRST_BOOT import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_IPSCRAMBLING_FLAG import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_WEEKLYREPORT import foundation.e.advancedprivacy.domain.entities.NotificationContent import foundation.e.advancedprivacy.domain.entities.weeklyreport.DisplayableReport import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule import foundation.e.advancedprivacy.features.weeklyreport.WeeklyReportViewFactory import foundation.e.advancedprivacy.main.MainActivity import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import timber.log.Timber object Notifications { fun showFirstBootNotification(context: Context) { createNotificationFirstBootChannel(context) // @SuppressLint("MissingPermission") class NotificationsPresenter( private val context: Context, private val getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, private val permissionsPrivacyModule: IPermissionsPrivacyModule, private val weeklyReportUseCase: WeeklyReportUseCase, private val weeklyReportViewFactory: WeeklyReportViewFactory, private val appScope: CoroutineScope ) { private val notificationManager = NotificationManagerCompat.from(context) fun showFirstBootNotification() { createNotificationFirstBootChannel() val notificationBuilder: NotificationCompat.Builder = notificationBuilder( context, NotificationContent( Loading @@ -61,49 +79,44 @@ object Notifications { ) .setAutoCancel(true) try { NotificationManagerCompat.from(context).notify( NOTIFICATION_FIRST_BOOT, notificationBuilder.build() ) } catch (e: SecurityException) { Timber.e(e, "Unexpected SecurityException while posting notification, we should have rights.") } } fun startListening( appContext: Context, getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, permissionsPrivacyModule: IPermissionsPrivacyModule, appScope: CoroutineScope ) { fun startListening() { createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_FAKE_LOCATION_FLAG, channelName = R.string.notifications_fake_location_channel_name, channelDescription = R.string.notifications_fake_location_channel_description ) createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_IPSCRAMBLING_FLAG, channelName = R.string.notifications_ipscrambling_channel_name, channelDescription = R.string.notifications_ipscrambling_channel_description ) createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_TRACKER_FLAG, channelName = R.string.notifications_tracker_channel_name, channelDescription = R.string.notifications_tracker_channel_description ) createWeeklyReportChannel() getQuickPrivacyStateUseCase.locationMode.map { it != FeatureMode.VULNERABLE }.distinctUntilChanged().onEach { if (it) { showFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG) showFlagNotification(NOTIFICATION_FAKE_LOCATION_FLAG) } else { hideFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG) hideFlagNotification(NOTIFICATION_FAKE_LOCATION_FLAG) } }.launchIn(appScope) Loading @@ -111,14 +124,22 @@ object Notifications { it != FeatureState.OFF }.distinctUntilChanged().onEach { if (it) { showFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG) showFlagNotification(NOTIFICATION_IPSCRAMBLING_FLAG) } else { hideFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG) hideFlagNotification(NOTIFICATION_IPSCRAMBLING_FLAG) } }.launchIn(appScope) weeklyReportUseCase.currentReport.map { report -> if (report != null) { showWeeklyReportNotification(report) } else { notificationManager.cancel(NOTIFICATION_WEEKLYREPORT) } }.launchIn(appScope) } private fun createNotificationFirstBootChannel(context: Context) { private fun createNotificationFirstBootChannel() { val channel = NotificationChannel( CHANNEL_FIRST_BOOT, context.getString(R.string.notifications_first_boot_channel_name), Loading @@ -127,13 +148,7 @@ object Notifications { NotificationManagerCompat.from(context).createNotificationChannel(channel) } private fun createNotificationFlagChannel( context: Context, permissionsPrivacyModule: IPermissionsPrivacyModule, channelId: String, @StringRes channelName: Int, @StringRes channelDescription: Int ) { private fun createNotificationFlagChannel(channelId: String, @StringRes channelName: Int, @StringRes channelDescription: Int) { val channel = NotificationChannel( channelId, context.getString(channelName), Loading @@ -144,10 +159,21 @@ object Notifications { NotificationManagerCompat.from(context).createNotificationChannel(channel) } private fun showFlagNotification(context: Context, id: Int) { private fun createWeeklyReportChannel() { val channel = NotificationChannel( CHANNEL_WEEKLYREPORT, context.getString(R.string.notifications_weeklyreport_channel_name), NotificationManager.IMPORTANCE_LOW ) channel.description = context.getString(R.string.notifications_weeklyreport_channel_description) permissionsPrivacyModule.setBlockable(channel) notificationManager.createNotificationChannel(channel) } private fun showFlagNotification(id: Int) { when (id) { NOTIFICATION_FAKE_LOCATION_FLAG -> showFlagNotification( context = context, id = NOTIFICATION_FAKE_LOCATION_FLAG, content = NotificationContent( channelId = CHANNEL_FAKE_LOCATION_FLAG, Loading @@ -160,7 +186,6 @@ object Notifications { ) ) NOTIFICATION_IPSCRAMBLING_FLAG -> showFlagNotification( context = context, id = NOTIFICATION_IPSCRAMBLING_FLAG, content = NotificationContent( channelId = CHANNEL_IPSCRAMBLING_FLAG, Loading @@ -176,15 +201,34 @@ object Notifications { } } private fun showFlagNotification(context: Context, id: Int, content: NotificationContent) { private fun showFlagNotification(id: Int, content: NotificationContent) { val builder = notificationBuilder(context, content) .setPriority(NotificationCompat.PRIORITY_LOW) .setOngoing(true) notificationManager.notify(id, builder.build()) } fun showWeeklyReportNotification(report: DisplayableReport) { val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_WEEKLYREPORT) weeklyReportViewFactory.populateNotification(report, notificationBuilder) notificationBuilder.setColor(ContextCompat.getColor(context, R.color.launcher_icon_background)) .setColorized(true) .setSmallIcon(R.drawable.ic_advanced_privacy_for_notification) notificationBuilder.setSmallIcon(R.drawable.ic_shield_alert) notificationBuilder.setAutoCancel(true) NotificationManagerCompat.from(context).notify(id, builder.build()) val goToTrackersIntent = MainActivity.deepLinkBuilder(context) .setDestination(R.id.trackersFragment) notificationBuilder.setContentIntent(goToTrackersIntent.createPendingIntent()) notificationManager.notify( NOTIFICATION_WEEKLYREPORT, notificationBuilder.build() ) } private fun hideFlagNotification(context: Context, id: Int) { private fun hideFlagNotification(id: Int) { NotificationManagerCompat.from(context).cancel(id) } } app/src/main/java/foundation/e/advancedprivacy/common/BootCompletedReceiver.kt +4 −3 Original line number Diff line number Diff line /* * Copyright (C) 2023 MURENA SAS * Copyright (C) 2022 - 2024 E FOUNDATION * Copyright (C) 2022 - 2025 E FOUNDATION * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading @@ -21,7 +21,7 @@ package foundation.e.advancedprivacy.common import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import foundation.e.advancedprivacy.Notifications import foundation.e.advancedprivacy.NotificationsPresenter import foundation.e.advancedprivacy.core.utils.goAsync import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import kotlinx.coroutines.CoroutineScope Loading @@ -31,12 +31,13 @@ class BootCompletedReceiver : BroadcastReceiver() { private val localStateRepository by inject<LocalStateRepository>(LocalStateRepository::class.java) private val backgroundScope by inject<CoroutineScope>(CoroutineScope::class.java) private val notificationsPresenter: NotificationsPresenter by inject(NotificationsPresenter::class.java) override fun onReceive(context: Context, intent: Intent?) { if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { goAsync(backgroundScope) { if (localStateRepository.isFirstBoot()) { Notifications.showFirstBootNotification(context) notificationsPresenter.showFirstBootNotification() localStateRepository.setFirstBoot(false) } } Loading app/src/main/java/foundation/e/advancedprivacy/features/debug/DebugWeeklyReportFragment.kt +8 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import foundation.e.advancedprivacy.NotificationsPresenter import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.BindingListAdapter import foundation.e.advancedprivacy.common.BindingViewHolder Loading @@ -51,6 +52,7 @@ class DebugWeeklyReportFragment : Fragment(R.layout.debug_weekly_report_fragment private val weeklyReportUseCase: WeeklyReportUseCase by inject() private val appListRepository: AppListRepository by inject() private val trackersRepository: TrackersRepository by inject() private val notificationsPresenter: NotificationsPresenter by inject() private val reportsFactory: WeeklyReportViewFactory by inject() private lateinit var binding: DebugWeeklyReportFragmentBinding Loading Loading @@ -94,6 +96,12 @@ class DebugWeeklyReportFragment : Fragment(R.layout.debug_weekly_report_fragment }" } holder.binding.showNotification.setOnClickListener { report.first?.let { notificationsPresenter.showWeeklyReportNotification(it) } } holder.binding.share.setOnClickListener { val bmp = report.first?.let { reportsFactory.createShareBmp(requireContext(), it) Loading Loading
app/src/main/java/foundation/e/advancedprivacy/AdvancedPrivacyApplication.kt +1 −7 Original line number Diff line number Diff line Loading @@ -27,7 +27,6 @@ import foundation.e.advancedprivacy.domain.usecases.ShowFeaturesWarningUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStateUseCase import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase import foundation.e.advancedprivacy.domain.usecases.VpnSupervisorUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule import foundation.e.advancedprivacy.externalinterfaces.workers.WeeklyReportWorker import foundation.e.advancedprivacy.trackers.services.UpdateTrackersWorker import foundation.e.lib.telemetry.Telemetry Loading Loading @@ -64,12 +63,7 @@ class AdvancedPrivacyApplication : Application() { get(TrackersStatisticsUseCase::class.java) ) Notifications.startListening( this, get(GetQuickPrivacyStateUseCase::class.java), get(IPermissionsPrivacyModule::class.java), get(CoroutineScope::class.java) ) get<NotificationsPresenter>(NotificationsPresenter::class.java).startListening() get<IpScramblingStateUseCase>(IpScramblingStateUseCase::class.java) get<TrackersStateUseCase>(TrackersStateUseCase::class.java) Loading
app/src/main/java/foundation/e/advancedprivacy/KoinModule.kt +11 −0 Original line number Diff line number Diff line Loading @@ -229,4 +229,15 @@ val appModule = module { viewModelOf(::DashboardViewModel) single { WeeklyReportViewFactory() } single { NotificationsPresenter( context = androidContext(), getQuickPrivacyStateUseCase = get(), permissionsPrivacyModule = get(), weeklyReportUseCase = get(), weeklyReportViewFactory = get(), appScope = get() ) } }
app/src/main/java/foundation/e/advancedprivacy/Notifications.kt→app/src/main/java/foundation/e/advancedprivacy/NotificationsPresenter.kt +82 −38 Original line number Diff line number Diff line /* * Copyright (C) 2024 E FOUNDATION * Copyright (C) 2024 - 2025 E FOUNDATION * Copyright (C) 2022 - 2023 MURENA SAS * * This program is free software: you can redistribute it and/or modify Loading @@ -24,29 +24,47 @@ import android.content.Context import androidx.annotation.StringRes import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat import foundation.e.advancedprivacy.core.utils.notificationBuilder import foundation.e.advancedprivacy.domain.entities.CHANNEL_FAKE_LOCATION_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_FIRST_BOOT import foundation.e.advancedprivacy.domain.entities.CHANNEL_IPSCRAMBLING_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_TRACKER_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_WEEKLYREPORT import foundation.e.advancedprivacy.domain.entities.FeatureMode import foundation.e.advancedprivacy.domain.entities.FeatureState import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FAKE_LOCATION_FLAG import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FIRST_BOOT import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_IPSCRAMBLING_FLAG import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_WEEKLYREPORT import foundation.e.advancedprivacy.domain.entities.NotificationContent import foundation.e.advancedprivacy.domain.entities.weeklyreport.DisplayableReport import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.advancedprivacy.domain.usecases.WeeklyReportUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule import foundation.e.advancedprivacy.features.weeklyreport.WeeklyReportViewFactory import foundation.e.advancedprivacy.main.MainActivity import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import timber.log.Timber object Notifications { fun showFirstBootNotification(context: Context) { createNotificationFirstBootChannel(context) // @SuppressLint("MissingPermission") class NotificationsPresenter( private val context: Context, private val getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, private val permissionsPrivacyModule: IPermissionsPrivacyModule, private val weeklyReportUseCase: WeeklyReportUseCase, private val weeklyReportViewFactory: WeeklyReportViewFactory, private val appScope: CoroutineScope ) { private val notificationManager = NotificationManagerCompat.from(context) fun showFirstBootNotification() { createNotificationFirstBootChannel() val notificationBuilder: NotificationCompat.Builder = notificationBuilder( context, NotificationContent( Loading @@ -61,49 +79,44 @@ object Notifications { ) .setAutoCancel(true) try { NotificationManagerCompat.from(context).notify( NOTIFICATION_FIRST_BOOT, notificationBuilder.build() ) } catch (e: SecurityException) { Timber.e(e, "Unexpected SecurityException while posting notification, we should have rights.") } } fun startListening( appContext: Context, getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, permissionsPrivacyModule: IPermissionsPrivacyModule, appScope: CoroutineScope ) { fun startListening() { createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_FAKE_LOCATION_FLAG, channelName = R.string.notifications_fake_location_channel_name, channelDescription = R.string.notifications_fake_location_channel_description ) createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_IPSCRAMBLING_FLAG, channelName = R.string.notifications_ipscrambling_channel_name, channelDescription = R.string.notifications_ipscrambling_channel_description ) createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_TRACKER_FLAG, channelName = R.string.notifications_tracker_channel_name, channelDescription = R.string.notifications_tracker_channel_description ) createWeeklyReportChannel() getQuickPrivacyStateUseCase.locationMode.map { it != FeatureMode.VULNERABLE }.distinctUntilChanged().onEach { if (it) { showFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG) showFlagNotification(NOTIFICATION_FAKE_LOCATION_FLAG) } else { hideFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG) hideFlagNotification(NOTIFICATION_FAKE_LOCATION_FLAG) } }.launchIn(appScope) Loading @@ -111,14 +124,22 @@ object Notifications { it != FeatureState.OFF }.distinctUntilChanged().onEach { if (it) { showFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG) showFlagNotification(NOTIFICATION_IPSCRAMBLING_FLAG) } else { hideFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG) hideFlagNotification(NOTIFICATION_IPSCRAMBLING_FLAG) } }.launchIn(appScope) weeklyReportUseCase.currentReport.map { report -> if (report != null) { showWeeklyReportNotification(report) } else { notificationManager.cancel(NOTIFICATION_WEEKLYREPORT) } }.launchIn(appScope) } private fun createNotificationFirstBootChannel(context: Context) { private fun createNotificationFirstBootChannel() { val channel = NotificationChannel( CHANNEL_FIRST_BOOT, context.getString(R.string.notifications_first_boot_channel_name), Loading @@ -127,13 +148,7 @@ object Notifications { NotificationManagerCompat.from(context).createNotificationChannel(channel) } private fun createNotificationFlagChannel( context: Context, permissionsPrivacyModule: IPermissionsPrivacyModule, channelId: String, @StringRes channelName: Int, @StringRes channelDescription: Int ) { private fun createNotificationFlagChannel(channelId: String, @StringRes channelName: Int, @StringRes channelDescription: Int) { val channel = NotificationChannel( channelId, context.getString(channelName), Loading @@ -144,10 +159,21 @@ object Notifications { NotificationManagerCompat.from(context).createNotificationChannel(channel) } private fun showFlagNotification(context: Context, id: Int) { private fun createWeeklyReportChannel() { val channel = NotificationChannel( CHANNEL_WEEKLYREPORT, context.getString(R.string.notifications_weeklyreport_channel_name), NotificationManager.IMPORTANCE_LOW ) channel.description = context.getString(R.string.notifications_weeklyreport_channel_description) permissionsPrivacyModule.setBlockable(channel) notificationManager.createNotificationChannel(channel) } private fun showFlagNotification(id: Int) { when (id) { NOTIFICATION_FAKE_LOCATION_FLAG -> showFlagNotification( context = context, id = NOTIFICATION_FAKE_LOCATION_FLAG, content = NotificationContent( channelId = CHANNEL_FAKE_LOCATION_FLAG, Loading @@ -160,7 +186,6 @@ object Notifications { ) ) NOTIFICATION_IPSCRAMBLING_FLAG -> showFlagNotification( context = context, id = NOTIFICATION_IPSCRAMBLING_FLAG, content = NotificationContent( channelId = CHANNEL_IPSCRAMBLING_FLAG, Loading @@ -176,15 +201,34 @@ object Notifications { } } private fun showFlagNotification(context: Context, id: Int, content: NotificationContent) { private fun showFlagNotification(id: Int, content: NotificationContent) { val builder = notificationBuilder(context, content) .setPriority(NotificationCompat.PRIORITY_LOW) .setOngoing(true) notificationManager.notify(id, builder.build()) } fun showWeeklyReportNotification(report: DisplayableReport) { val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_WEEKLYREPORT) weeklyReportViewFactory.populateNotification(report, notificationBuilder) notificationBuilder.setColor(ContextCompat.getColor(context, R.color.launcher_icon_background)) .setColorized(true) .setSmallIcon(R.drawable.ic_advanced_privacy_for_notification) notificationBuilder.setSmallIcon(R.drawable.ic_shield_alert) notificationBuilder.setAutoCancel(true) NotificationManagerCompat.from(context).notify(id, builder.build()) val goToTrackersIntent = MainActivity.deepLinkBuilder(context) .setDestination(R.id.trackersFragment) notificationBuilder.setContentIntent(goToTrackersIntent.createPendingIntent()) notificationManager.notify( NOTIFICATION_WEEKLYREPORT, notificationBuilder.build() ) } private fun hideFlagNotification(context: Context, id: Int) { private fun hideFlagNotification(id: Int) { NotificationManagerCompat.from(context).cancel(id) } }
app/src/main/java/foundation/e/advancedprivacy/common/BootCompletedReceiver.kt +4 −3 Original line number Diff line number Diff line /* * Copyright (C) 2023 MURENA SAS * Copyright (C) 2022 - 2024 E FOUNDATION * Copyright (C) 2022 - 2025 E FOUNDATION * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Loading @@ -21,7 +21,7 @@ package foundation.e.advancedprivacy.common import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import foundation.e.advancedprivacy.Notifications import foundation.e.advancedprivacy.NotificationsPresenter import foundation.e.advancedprivacy.core.utils.goAsync import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository import kotlinx.coroutines.CoroutineScope Loading @@ -31,12 +31,13 @@ class BootCompletedReceiver : BroadcastReceiver() { private val localStateRepository by inject<LocalStateRepository>(LocalStateRepository::class.java) private val backgroundScope by inject<CoroutineScope>(CoroutineScope::class.java) private val notificationsPresenter: NotificationsPresenter by inject(NotificationsPresenter::class.java) override fun onReceive(context: Context, intent: Intent?) { if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { goAsync(backgroundScope) { if (localStateRepository.isFirstBoot()) { Notifications.showFirstBootNotification(context) notificationsPresenter.showFirstBootNotification() localStateRepository.setFirstBoot(false) } } Loading
app/src/main/java/foundation/e/advancedprivacy/features/debug/DebugWeeklyReportFragment.kt +8 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import foundation.e.advancedprivacy.NotificationsPresenter import foundation.e.advancedprivacy.R import foundation.e.advancedprivacy.common.BindingListAdapter import foundation.e.advancedprivacy.common.BindingViewHolder Loading @@ -51,6 +52,7 @@ class DebugWeeklyReportFragment : Fragment(R.layout.debug_weekly_report_fragment private val weeklyReportUseCase: WeeklyReportUseCase by inject() private val appListRepository: AppListRepository by inject() private val trackersRepository: TrackersRepository by inject() private val notificationsPresenter: NotificationsPresenter by inject() private val reportsFactory: WeeklyReportViewFactory by inject() private lateinit var binding: DebugWeeklyReportFragmentBinding Loading Loading @@ -94,6 +96,12 @@ class DebugWeeklyReportFragment : Fragment(R.layout.debug_weekly_report_fragment }" } holder.binding.showNotification.setOnClickListener { report.first?.let { notificationsPresenter.showWeeklyReportNotification(it) } } holder.binding.share.setOnClickListener { val bmp = report.first?.let { reportsFactory.createShareBmp(requireContext(), it) Loading