Add security option to disallow screenshots

This commit is contained in:
PhilKes 2025-04-18 16:08:54 +02:00 committed by Phil
parent adb981d76c
commit 2c1f5d5338
8 changed files with 50 additions and 1 deletions

View file

@ -1,15 +1,18 @@
package com.philkes.notallyx package com.philkes.notallyx
import android.app.Activity
import android.app.Application import android.app.Application
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.os.Build import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.work.WorkInfo import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import com.philkes.notallyx.presentation.setEnabledSecureFlag
import com.philkes.notallyx.presentation.view.misc.NotNullLiveData import com.philkes.notallyx.presentation.view.misc.NotNullLiveData
import com.philkes.notallyx.presentation.viewmodel.preference.BiometricLock import com.philkes.notallyx.presentation.viewmodel.preference.BiometricLock
import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences import com.philkes.notallyx.presentation.viewmodel.preference.NotallyXPreferences
@ -33,7 +36,7 @@ import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class NotallyXApplication : Application() { class NotallyXApplication : Application(), Application.ActivityLifecycleCallbacks {
private lateinit var biometricLockObserver: Observer<BiometricLock> private lateinit var biometricLockObserver: Observer<BiometricLock>
private lateinit var preferences: NotallyXPreferences private lateinit var preferences: NotallyXPreferences
@ -43,6 +46,7 @@ class NotallyXApplication : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
registerActivityLifecycleCallbacks(this)
if (isTestRunner()) return if (isTestRunner()) return
preferences = NotallyXPreferences.getInstance(this) preferences = NotallyXPreferences.getInstance(this)
if (preferences.useDynamicColors.value) { if (preferences.useDynamicColors.value) {
@ -168,4 +172,20 @@ class NotallyXApplication : Application() {
return Build.FINGERPRINT.equals("robolectric", ignoreCase = true) return Build.FINGERPRINT.equals("robolectric", ignoreCase = true)
} }
} }
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
activity.setEnabledSecureFlag(preferences.secureFlag.value)
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
} }

View file

@ -531,6 +531,17 @@ fun Activity.checkAlarmPermission(
} else onSuccess() } else onSuccess()
} }
fun Activity.setEnabledSecureFlag(enabled: Boolean) {
if (enabled) {
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE,
)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
}
fun Fragment.displayEditLabelDialog( fun Fragment.displayEditLabelDialog(
oldValue: String, oldValue: String,
model: BaseNoteModel, model: BaseNoteModel,

View file

@ -33,6 +33,7 @@ import com.philkes.notallyx.databinding.DialogTextInputBinding
import com.philkes.notallyx.databinding.FragmentSettingsBinding import com.philkes.notallyx.databinding.FragmentSettingsBinding
import com.philkes.notallyx.presentation.activity.main.MainActivity import com.philkes.notallyx.presentation.activity.main.MainActivity
import com.philkes.notallyx.presentation.setCancelButton import com.philkes.notallyx.presentation.setCancelButton
import com.philkes.notallyx.presentation.setEnabledSecureFlag
import com.philkes.notallyx.presentation.setupImportProgressDialog import com.philkes.notallyx.presentation.setupImportProgressDialog
import com.philkes.notallyx.presentation.setupProgressDialog import com.philkes.notallyx.presentation.setupProgressDialog
import com.philkes.notallyx.presentation.showAndFocus import com.philkes.notallyx.presentation.showAndFocus
@ -592,6 +593,14 @@ class SettingsFragment : Fragment() {
model.savePreference(backupPassword, newValue) model.savePreference(backupPassword, newValue)
} }
} }
secureFlag.observe(viewLifecycleOwner) { value ->
binding.SecureFlag.setup(secureFlag, value, requireContext(), layoutInflater) { newValue
->
model.savePreference(secureFlag, newValue)
activity?.setEnabledSecureFlag(newValue)
}
}
} }
private fun NotallyXPreferences.setupSettings(binding: FragmentSettingsBinding) { private fun NotallyXPreferences.setupSettings(binding: FragmentSettingsBinding) {

View file

@ -135,6 +135,8 @@ class NotallyXPreferences private constructor(private val context: Context) {
val fallbackDatabaseEncryptionKey by lazy { val fallbackDatabaseEncryptionKey by lazy {
ByteArrayPreference("fallback_database_encryption_key", encryptedPreferences, ByteArray(0)) ByteArrayPreference("fallback_database_encryption_key", encryptedPreferences, ByteArray(0))
} }
val secureFlag =
BooleanPreference("secureFlag", preferences, false, R.string.disallow_screenshots)
val dataInPublicFolder = val dataInPublicFolder =
BooleanPreference("dataOnExternalStorage", preferences, false, R.string.data_in_public) BooleanPreference("dataOnExternalStorage", preferences, false, R.string.data_in_public)
@ -223,6 +225,7 @@ class NotallyXPreferences private constructor(private val context: Context) {
maxItems, maxItems,
maxLines, maxLines,
maxTitle, maxTitle,
secureFlag,
labelsHidden, labelsHidden,
labelTagsHiddenInOverview, labelTagsHiddenInOverview,
maxLabels, maxLabels,

View file

@ -173,6 +173,10 @@
android:id="@+id/BackupPassword" android:id="@+id/BackupPassword"
layout="@layout/preference" /> layout="@layout/preference" />
<include
android:id="@+id/SecureFlag"
layout="@layout/preference" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"

View file

@ -119,6 +119,7 @@
<string name="disable_lock_description">Dies entschlüsselt außerdem die Datenbank</string> <string name="disable_lock_description">Dies entschlüsselt außerdem die Datenbank</string>
<string name="disable_lock_title">Deaktivierte Biometrie/PIN Sperre</string> <string name="disable_lock_title">Deaktivierte Biometrie/PIN Sperre</string>
<string name="disabled">Deaktiviert</string> <string name="disabled">Deaktiviert</string>
<string name="disallow_screenshots">Screenshots verbieten</string>
<string name="discard">Verwerfen</string> <string name="discard">Verwerfen</string>
<string name="display_text">Anzeigetext</string> <string name="display_text">Anzeigetext</string>
<string name="donate">Spende</string> <string name="donate">Spende</string>

View file

@ -121,6 +121,7 @@
<string name="disable_lock_description">This will also decrypt the database</string> <string name="disable_lock_description">This will also decrypt the database</string>
<string name="disable_lock_title">Disable lock via Biometric/PIN</string> <string name="disable_lock_title">Disable lock via Biometric/PIN</string>
<string name="disabled">Disabled</string> <string name="disabled">Disabled</string>
<string name="disallow_screenshots">Disallow Screenshots</string>
<string name="discard">Discard</string> <string name="discard">Discard</string>
<string name="display_text">Text to display</string> <string name="display_text">Text to display</string>
<string name="donate">Make a Donation</string> <string name="donate">Make a Donation</string>

Binary file not shown.