Skip to content

Commit 7e71c3b

Browse files
committed
Make keyboard actually directBootAware.
Wait to load clippings once we have unlocked the device just in case someone stores important data there.
1 parent 467ca9b commit 7e71c3b

File tree

5 files changed

+112
-42
lines changed

5 files changed

+112
-42
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616
<activity
1717
android:name=".SettingsActivity"
1818
android:exported="true"
19-
android:label="@string/ime_settings">
19+
android:label="@string/ime_settings"
20+
android:directBootAware="true">
2021
<intent-filter>
2122
<action android:name="android.intent.action.MAIN" />
2223
<category android:name="android.intent.category.LAUNCHER" />
2324
</intent-filter>
25+
<intent-filter>
26+
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
27+
<category android:name="android.intent.category.DEFAULT" />
28+
</intent-filter>
2429
</activity>
2530

2631
<service
@@ -30,6 +35,7 @@
3035
android:label="@string/ime_label"
3136
android:permission="android.permission.BIND_INPUT_METHOD"
3237
android:directBootAware="true">
38+
3339
<intent-filter>
3440
<action android:name="android.view.InputMethod" />
3541
</intent-filter>

app/src/main/java/io/github/rickybrent/minimal_symlayer_keyboard/ClipboardHistoryManager.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import androidx.core.content.edit
99
object ClipboardHistoryManager {
1010
private val clipboardHistory = mutableListOf<Clipping>()
1111
private var clipboardManager: ClipboardManager? = null
12-
private lateinit var prefs: SharedPreferences
12+
private var prefs: SharedPreferences? = null
1313

1414
private const val PREF_PINNED_CLIPPINGS = "pinned_clippings"
1515

@@ -34,21 +34,26 @@ object ClipboardHistoryManager {
3434
if (clipboardManager == null) {
3535
clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
3636
clipboardManager?.addPrimaryClipChangedListener(clipboardListener)
37-
prefs = context.getSharedPreferences(PREF_PINNED_CLIPPINGS, Context.MODE_PRIVATE)
38-
loadPinnedClippings()
3937
}
4038
}
4139

42-
private fun loadPinnedClippings() {
43-
val pinnedItems = prefs.getStringSet(PREF_PINNED_CLIPPINGS, emptySet()) ?: emptySet()
40+
fun loadPinnedClippings(context: Context) {
41+
if (prefs == null) {
42+
prefs = context.getSharedPreferences("clipboard_history", Context.MODE_PRIVATE)
43+
}
44+
val pinnedItems = prefs?.getStringSet(PREF_PINNED_CLIPPINGS, emptySet()) ?: emptySet()
4445
pinnedItems.forEach {
45-
clipboardHistory.add(Clipping(it, isPinned = true))
46+
if (clipboardHistory.none { clipping -> clipping.text == it }) {
47+
clipboardHistory.add(Clipping(it, isPinned = true))
48+
}
4649
}
4750
}
4851

4952
private fun savePinnedClippings() {
50-
val pinnedItems = clipboardHistory.filter { it.isPinned }.map { it.text }.toSet()
51-
prefs.edit { putStringSet(PREF_PINNED_CLIPPINGS, pinnedItems) }
53+
prefs?.let { it ->
54+
val pinnedItems = clipboardHistory.filter { it.isPinned }.map { it.text }.toSet()
55+
it.edit { putStringSet(PREF_PINNED_CLIPPINGS, pinnedItems) }
56+
}
5257
}
5358

5459
fun getHistory(): List<Clipping> {

app/src/main/java/io/github/rickybrent/minimal_symlayer_keyboard/InputMethodService.kt

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.github.rickybrent.minimal_symlayer_keyboard
22

3+
import android.content.BroadcastReceiver
34
import android.content.Context
45
import android.content.Intent
6+
import android.content.IntentFilter
7+
import android.os.Build
58
import android.provider.Settings
69
import android.os.VibrationEffect
710
import android.os.Vibrator
@@ -200,16 +203,28 @@ class InputMethodService : AndroidInputMethodService() {
200203
)
201204
))
202205

206+
private val unlockReceiver = object : BroadcastReceiver() {
207+
override fun onReceive(context: Context?, intent: Intent?) {
208+
if (intent?.action == Intent.ACTION_USER_UNLOCKED) {
209+
ClipboardHistoryManager.loadPinnedClippings(this@InputMethodService)
210+
updateFromPreferences()
211+
}
212+
}
213+
}
214+
203215
override fun onCreate() {
204216
super.onCreate()
205-
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
206-
ClipboardHistoryManager.initialize(this)
217+
val context = createDeviceProtectedStorageContext()
218+
ClipboardHistoryManager.initialize(context)
207219

208-
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
220+
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
209221
preferences.registerOnSharedPreferenceChangeListener { _, _ ->
210222
updateFromPreferences()
211223
}
212224
updateFromPreferences()
225+
val filter = IntentFilter(Intent.ACTION_USER_UNLOCKED)
226+
registerReceiver(unlockReceiver, filter)
227+
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
213228
}
214229

215230
private fun showEmojiPicker() {
@@ -219,12 +234,12 @@ class InputMethodService : AndroidInputMethodService() {
219234
pickerManager?.show()
220235
}
221236

222-
private fun showClipboardHistory() {
223-
if (pickerManager == null) {
224-
pickerManager = PickerManager(this, this)
225-
}
226-
pickerManager?.show(PickerManager.ViewType.CLIPBOARD)
227-
}
237+
private fun showClipboardHistory() {
238+
if (pickerManager == null) {
239+
pickerManager = PickerManager(this, this)
240+
}
241+
pickerManager?.show(PickerManager.ViewType.CLIPBOARD)
242+
}
228243

229244
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
230245
super.onStartInput(attribute, restarting)
@@ -775,7 +790,8 @@ class InputMethodService : AndroidInputMethodService() {
775790
* Update values from the preferences.
776791
*/
777792
private fun updateFromPreferences() {
778-
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
793+
val context = createDeviceProtectedStorageContext()
794+
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
779795

780796
autoCapitalize = preferences.getBoolean("AutoCapitalize", true)
781797

app/src/main/java/io/github/rickybrent/minimal_symlayer_keyboard/SettingsActivity.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package io.github.rickybrent.minimal_symlayer_keyboard
22

3+
import android.content.Context
34
import android.content.DialogInterface
45
import android.content.Intent
56
import android.net.Uri
7+
import android.os.Build
68
import android.os.Bundle
79
import android.view.Menu
810
import android.view.MenuItem
@@ -14,6 +16,8 @@ import androidx.preference.Preference
1416
import androidx.preference.PreferenceFragmentCompat
1517
import androidx.preference.PreferenceGroup
1618
import androidx.preference.PreferenceManager
19+
import androidx.preference.PreferenceDataStore
20+
import androidx.core.content.edit
1721

1822
class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
1923

@@ -85,6 +89,7 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
8589

8690
class SettingsFragment : PreferenceFragmentCompat() {
8791
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
92+
preferenceManager.preferenceDataStore = DeviceProtectedPreferenceDataStore(requireContext())
8893
setPreferencesFromResource(R.xml.preferences, rootKey)
8994
val context = activity
9095
if(context != null) {
@@ -233,4 +238,42 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
233238
.show()
234239
}
235240
}
241+
}
242+
243+
class DeviceProtectedPreferenceDataStore(context: Context) : PreferenceDataStore() {
244+
private val sharedPreferences by lazy {
245+
val storageContext = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
246+
context.createDeviceProtectedStorageContext()
247+
} else {
248+
context
249+
}
250+
storageContext.getSharedPreferences(
251+
"${context.packageName}_preferences",
252+
Context.MODE_PRIVATE
253+
)
254+
}
255+
256+
override fun putString(key: String?, value: String?) {
257+
sharedPreferences.edit { putString(key, value) }
258+
}
259+
260+
override fun getString(key: String?, defValue: String?): String? {
261+
return sharedPreferences.getString(key, defValue)
262+
}
263+
264+
override fun putBoolean(key: String?, value: Boolean) {
265+
sharedPreferences.edit { putBoolean(key, value) }
266+
}
267+
268+
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
269+
return sharedPreferences.getBoolean(key, defValue)
270+
}
271+
272+
override fun putInt(key: String?, value: Int) {
273+
sharedPreferences.edit { putInt(key, value) }
274+
}
275+
276+
override fun getInt(key: String?, defValue: Int): Int {
277+
return sharedPreferences.getInt(key, defValue)
278+
}
236279
}

app/src/main/res/xml/preferences.xml

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,31 @@
1717
/>
1818
</PreferenceCategory>
1919
<PreferenceCategory android:title="Special Keys" >
20-
<Preference
21-
app:summary="Assign actions for tap, long press, and hold + key combinations for certain keys."
22-
app:selectable="false"/>
20+
<Preference
21+
app:summary="Assign actions for tap, long press, and hold + key combinations for certain keys."
22+
app:selectable="false"/>
2323

24-
<io.github.rickybrent.minimal_symlayer_keyboard.SpecialKeyPreference
25-
app:key="pref_dotctrl"
26-
app:title="Mic/Period"
27-
app:keyIcon="@drawable/ic_key_dotvoice"
28-
app:tapEntries="@array/dotctrl_tap_entries"
29-
app:tapValues="@array/dotctrl_tap_values"
30-
app:longPressEntries="@array/dotctrl_long_press_entries"
31-
app:longPressValues="@array/dotctrl_long_press_values"
32-
app:holdEntries="@array/dotctrl_hold_entries"
33-
app:holdValues="@array/dotctrl_hold_values" />
24+
<io.github.rickybrent.minimal_symlayer_keyboard.SpecialKeyPreference
25+
app:key="pref_dotctrl"
26+
app:title="Mic/Period"
27+
app:keyIcon="@drawable/ic_key_dotvoice"
28+
app:tapEntries="@array/dotctrl_tap_entries"
29+
app:tapValues="@array/dotctrl_tap_values"
30+
app:longPressEntries="@array/dotctrl_long_press_entries"
31+
app:longPressValues="@array/dotctrl_long_press_values"
32+
app:holdEntries="@array/dotctrl_hold_entries"
33+
app:holdValues="@array/dotctrl_hold_values" />
3434

35-
<io.github.rickybrent.minimal_symlayer_keyboard.SpecialKeyPreference
36-
app:key="pref_emojimeta"
37-
app:title="Emoji/0"
38-
app:keyIcon="@drawable/ic_key_emoji0"
39-
app:tapEntries="@array/emojimeta_tap_entries"
40-
app:tapValues="@array/emojimeta_tap_values"
41-
app:longPressEntries="@array/emojimeta_long_press_entries"
42-
app:longPressValues="@array/emojimeta_long_press_values"
43-
app:holdEntries="@array/emojimeta_hold_entries"
44-
app:holdValues="@array/emojimeta_hold_values" />
35+
<io.github.rickybrent.minimal_symlayer_keyboard.SpecialKeyPreference
36+
app:key="pref_emojimeta"
37+
app:title="Emoji/0"
38+
app:keyIcon="@drawable/ic_key_emoji0"
39+
app:tapEntries="@array/emojimeta_tap_entries"
40+
app:tapValues="@array/emojimeta_tap_values"
41+
app:longPressEntries="@array/emojimeta_long_press_entries"
42+
app:longPressValues="@array/emojimeta_long_press_values"
43+
app:holdEntries="@array/emojimeta_hold_entries"
44+
app:holdValues="@array/emojimeta_hold_values" />
4545
</PreferenceCategory>
4646
<PreferenceCategory android:title="Accented characters">
4747
<SwitchPreference

0 commit comments

Comments
 (0)