mirror of
https://github.com/SimpleMobileTools/Simple-SMS-Messenger.git
synced 2025-02-19 21:20:39 +01:00
Merge pull request #672 from esensar/feature/446-password-protection
Add password protection feature to the app
This commit is contained in:
commit
b0da7bad31
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.USE_FINGERPRINT"
|
android:name="android.permission.USE_BIOMETRIC"
|
||||||
tools:node="remove" />
|
tools:node="remove" />
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
@ -55,9 +55,9 @@
|
|||||||
android:name=".activities.ThreadActivity"
|
android:name=".activities.ThreadActivity"
|
||||||
android:configChanges="orientation"
|
android:configChanges="orientation"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
android:launchMode="singleTop"
|
||||||
android:parentActivityName=".activities.MainActivity"
|
android:parentActivityName=".activities.MainActivity"
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize" />
|
||||||
android:launchMode="singleTop" />
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.NewConversationActivity"
|
android:name=".activities.NewConversationActivity"
|
||||||
|
@ -50,6 +50,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
private var lastSearchedText = ""
|
private var lastSearchedText = ""
|
||||||
private var bus: EventBus? = null
|
private var bus: EventBus? = null
|
||||||
private val smsExporter by lazy { MessagesExporter(this) }
|
private val smsExporter by lazy { MessagesExporter(this) }
|
||||||
|
private var wasProtectionHandled = false
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -62,31 +63,19 @@ class MainActivity : SimpleActivity() {
|
|||||||
|
|
||||||
updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true)
|
updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true)
|
||||||
|
|
||||||
if (checkAppSideloading()) {
|
if (savedInstanceState == null) {
|
||||||
return
|
handleAppPasswordProtection {
|
||||||
|
wasProtectionHandled = it
|
||||||
|
if (it) {
|
||||||
|
loadMessages()
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isQPlus()) {
|
if (checkAppSideloading()) {
|
||||||
val roleManager = getSystemService(RoleManager::class.java)
|
return
|
||||||
if (roleManager!!.isRoleAvailable(RoleManager.ROLE_SMS)) {
|
|
||||||
if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
|
|
||||||
askPermissions()
|
|
||||||
} else {
|
|
||||||
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS)
|
|
||||||
startActivityForResult(intent, MAKE_DEFAULT_APP_REQUEST)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toast(R.string.unknown_error_occurred)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (Telephony.Sms.getDefaultSmsPackage(this) == packageName) {
|
|
||||||
askPermissions()
|
|
||||||
} else {
|
|
||||||
val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
|
|
||||||
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName)
|
|
||||||
startActivityForResult(intent, MAKE_DEFAULT_APP_REQUEST)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAllMessagesIfNeeded()
|
clearAllMessagesIfNeeded()
|
||||||
@ -140,6 +129,29 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putBoolean(WAS_PROTECTION_HANDLED, wasProtectionHandled)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||||
|
super.onRestoreInstanceState(savedInstanceState)
|
||||||
|
wasProtectionHandled = savedInstanceState.getBoolean(WAS_PROTECTION_HANDLED, false)
|
||||||
|
|
||||||
|
if (!wasProtectionHandled) {
|
||||||
|
handleAppPasswordProtection {
|
||||||
|
wasProtectionHandled = it
|
||||||
|
if (it) {
|
||||||
|
loadMessages()
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loadMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupOptionsMenu() {
|
private fun setupOptionsMenu() {
|
||||||
main_menu.getToolbar().inflateMenu(R.menu.menu_main)
|
main_menu.getToolbar().inflateMenu(R.menu.menu_main)
|
||||||
main_menu.toggleHideOnScroll(true)
|
main_menu.toggleHideOnScroll(true)
|
||||||
@ -205,6 +217,31 @@ class MainActivity : SimpleActivity() {
|
|||||||
main_menu.updateColors()
|
main_menu.updateColors()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadMessages() {
|
||||||
|
if (isQPlus()) {
|
||||||
|
val roleManager = getSystemService(RoleManager::class.java)
|
||||||
|
if (roleManager!!.isRoleAvailable(RoleManager.ROLE_SMS)) {
|
||||||
|
if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
|
||||||
|
askPermissions()
|
||||||
|
} else {
|
||||||
|
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS)
|
||||||
|
startActivityForResult(intent, MAKE_DEFAULT_APP_REQUEST)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast(R.string.unknown_error_occurred)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Telephony.Sms.getDefaultSmsPackage(this) == packageName) {
|
||||||
|
askPermissions()
|
||||||
|
} else {
|
||||||
|
val intent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
|
||||||
|
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName)
|
||||||
|
startActivityForResult(intent, MAKE_DEFAULT_APP_REQUEST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// while SEND_SMS and READ_SMS permissions are mandatory, READ_CONTACTS is optional. If we don't have it, we just won't be able to show the contact name in some cases
|
// while SEND_SMS and READ_SMS permissions are mandatory, READ_CONTACTS is optional. If we don't have it, we just won't be able to show the contact name in some cases
|
||||||
private fun askPermissions() {
|
private fun askPermissions() {
|
||||||
handlePermission(PERMISSION_READ_SMS) {
|
handlePermission(PERMISSION_READ_SMS) {
|
||||||
@ -410,6 +447,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
val conversation = any as Conversation
|
val conversation = any as Conversation
|
||||||
putExtra(THREAD_ID, conversation.threadId)
|
putExtra(THREAD_ID, conversation.threadId)
|
||||||
putExtra(THREAD_TITLE, conversation.title)
|
putExtra(THREAD_TITLE, conversation.title)
|
||||||
|
putExtra(WAS_PROTECTION_HANDLED, wasProtectionHandled)
|
||||||
startActivity(this)
|
startActivity(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -636,6 +674,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
showErrorToast(e)
|
showErrorToast(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> toast(R.string.invalid_file_format)
|
else -> toast(R.string.invalid_file_format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,7 @@ import android.content.Intent
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
|
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
|
||||||
import com.simplemobiletools.commons.dialogs.ChangeDateTimeFormatDialog
|
import com.simplemobiletools.commons.dialogs.*
|
||||||
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
|
|
||||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.*
|
import com.simplemobiletools.commons.helpers.*
|
||||||
import com.simplemobiletools.commons.models.RadioItem
|
import com.simplemobiletools.commons.models.RadioItem
|
||||||
@ -49,6 +47,7 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
setupGroupMessageAsMMS()
|
setupGroupMessageAsMMS()
|
||||||
setupLockScreenVisibility()
|
setupLockScreenVisibility()
|
||||||
setupMMSFileSizeLimit()
|
setupMMSFileSizeLimit()
|
||||||
|
setupAppPasswordProtection()
|
||||||
updateTextColors(settings_nested_scrollview)
|
updateTextColors(settings_nested_scrollview)
|
||||||
|
|
||||||
if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) {
|
if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) {
|
||||||
@ -59,7 +58,8 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
settings_color_customization_section_label,
|
settings_color_customization_section_label,
|
||||||
settings_general_settings_label,
|
settings_general_settings_label,
|
||||||
settings_outgoing_messages_label,
|
settings_outgoing_messages_label,
|
||||||
settings_notifications_label
|
settings_notifications_label,
|
||||||
|
settings_security_label
|
||||||
).forEach {
|
).forEach {
|
||||||
it.setTextColor(getProperPrimaryColor())
|
it.setTextColor(getProperPrimaryColor())
|
||||||
}
|
}
|
||||||
@ -244,6 +244,28 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupAppPasswordProtection() {
|
||||||
|
settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn
|
||||||
|
settings_app_password_protection_holder.setOnClickListener {
|
||||||
|
val tabToShow = if (config.isAppPasswordProtectionOn) config.appProtectionType else SHOW_ALL_TABS
|
||||||
|
SecurityDialog(this, config.appPasswordHash, tabToShow) { hash, type, success ->
|
||||||
|
if (success) {
|
||||||
|
val hasPasswordProtection = config.isAppPasswordProtectionOn
|
||||||
|
settings_app_password_protection.isChecked = !hasPasswordProtection
|
||||||
|
config.isAppPasswordProtectionOn = !hasPasswordProtection
|
||||||
|
config.appPasswordHash = if (hasPasswordProtection) "" else hash
|
||||||
|
config.appProtectionType = type
|
||||||
|
|
||||||
|
if (config.isAppPasswordProtectionOn) {
|
||||||
|
val confirmationTextId = if (config.appProtectionType == PROTECTION_FINGERPRINT)
|
||||||
|
R.string.fingerprint_setup_successfully else R.string.protection_setup_successfully
|
||||||
|
ConfirmationDialog(this, "", confirmationTextId, R.string.ok, 0) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getMMSFileLimitText() = getString(
|
private fun getMMSFileLimitText() = getString(
|
||||||
when (config.mmsFileSizeLimit) {
|
when (config.mmsFileSizeLimit) {
|
||||||
FILE_SIZE_100_KB -> R.string.mms_file_size_limit_100kb
|
FILE_SIZE_100_KB -> R.string.mms_file_size_limit_100kb
|
||||||
|
@ -101,6 +101,7 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
private var loadingOlderMessages = false
|
private var loadingOlderMessages = false
|
||||||
private var allMessagesFetched = false
|
private var allMessagesFetched = false
|
||||||
private var oldestMessageDate = -1
|
private var oldestMessageDate = -1
|
||||||
|
private var wasProtectionHandled = false
|
||||||
|
|
||||||
private var isScheduledMessage: Boolean = false
|
private var isScheduledMessage: Boolean = false
|
||||||
private var scheduledMessage: Message? = null
|
private var scheduledMessage: Message? = null
|
||||||
@ -136,28 +137,23 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
intent.getStringExtra(THREAD_TITLE)?.let {
|
intent.getStringExtra(THREAD_TITLE)?.let {
|
||||||
thread_toolbar.title = it
|
thread_toolbar.title = it
|
||||||
}
|
}
|
||||||
|
wasProtectionHandled = intent.getBooleanExtra(WAS_PROTECTION_HANDLED, false)
|
||||||
|
|
||||||
bus = EventBus.getDefault()
|
bus = EventBus.getDefault()
|
||||||
bus!!.register(this)
|
bus!!.register(this)
|
||||||
handlePermission(PERMISSION_READ_PHONE_STATE) { granted ->
|
|
||||||
if (granted) {
|
|
||||||
setupButtons()
|
|
||||||
setupConversation()
|
|
||||||
setupCachedMessages {
|
|
||||||
val searchedMessageId = intent.getLongExtra(SEARCHED_MESSAGE_ID, -1L)
|
|
||||||
intent.removeExtra(SEARCHED_MESSAGE_ID)
|
|
||||||
if (searchedMessageId != -1L) {
|
|
||||||
val index = threadItems.indexOfFirst { (it as? Message)?.id == searchedMessageId }
|
|
||||||
if (index != -1) {
|
|
||||||
thread_messages_list.smoothScrollToPosition(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setupThread()
|
if (savedInstanceState == null) {
|
||||||
setupScrollFab()
|
if (!wasProtectionHandled) {
|
||||||
|
handleAppPasswordProtection {
|
||||||
|
wasProtectionHandled = it
|
||||||
|
if (it) {
|
||||||
|
loadConversation()
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
finish()
|
loadConversation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +217,29 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
bus?.unregister(this)
|
bus?.unregister(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putBoolean(WAS_PROTECTION_HANDLED, wasProtectionHandled)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||||
|
super.onRestoreInstanceState(savedInstanceState)
|
||||||
|
wasProtectionHandled = savedInstanceState.getBoolean(WAS_PROTECTION_HANDLED, false)
|
||||||
|
|
||||||
|
if (!wasProtectionHandled) {
|
||||||
|
handleAppPasswordProtection {
|
||||||
|
wasProtectionHandled = it
|
||||||
|
if (it) {
|
||||||
|
loadConversation()
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loadConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun refreshMenuItems() {
|
private fun refreshMenuItems() {
|
||||||
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
|
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
|
||||||
thread_toolbar.menu.apply {
|
thread_toolbar.menu.apply {
|
||||||
@ -546,6 +565,30 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadConversation() {
|
||||||
|
handlePermission(PERMISSION_READ_PHONE_STATE) { granted ->
|
||||||
|
if (granted) {
|
||||||
|
setupButtons()
|
||||||
|
setupConversation()
|
||||||
|
setupCachedMessages {
|
||||||
|
val searchedMessageId = intent.getLongExtra(SEARCHED_MESSAGE_ID, -1L)
|
||||||
|
intent.removeExtra(SEARCHED_MESSAGE_ID)
|
||||||
|
if (searchedMessageId != -1L) {
|
||||||
|
val index = threadItems.indexOfFirst { (it as? Message)?.id == searchedMessageId }
|
||||||
|
if (index != -1) {
|
||||||
|
thread_messages_list.smoothScrollToPosition(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupThread()
|
||||||
|
setupScrollFab()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupConversation() {
|
private fun setupConversation() {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
conversation = conversationsDB.getConversationWithThreadId(threadId)
|
conversation = conversationsDB.getConversationWithThreadId(threadId)
|
||||||
|
@ -341,6 +341,32 @@
|
|||||||
tools:text="@string/mms_file_size_limit_none" />
|
tools:text="@string/mms_file_size_limit_none" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/settings_outgoing_messages_divider"
|
||||||
|
layout="@layout/divider" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/settings_security_label"
|
||||||
|
style="@style/SettingsSectionLabelStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/security" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/settings_app_password_protection_holder"
|
||||||
|
style="@style/SettingsHolderCheckboxStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||||
|
android:id="@+id/settings_app_password_protection"
|
||||||
|
style="@style/SettingsCheckboxStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/password_protect_whole_app" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user