From c42de6f827318fa561cb1e9791f84c668cd689ac Mon Sep 17 00:00:00 2001 From: Moez Bhatti Date: Tue, 4 Sep 2018 22:08:40 -0400 Subject: [PATCH] Request SMS permission when sending message --- .../java/com/moez/QKSMS/manager/PermissionManagerImpl.kt | 6 ++---- .../com/moez/QKSMS/mapper/CursorToConversationImpl.kt | 2 +- .../java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt | 2 +- .../java/com/moez/QKSMS/mapper/CursorToRecipientImpl.kt | 2 +- .../main/java/com/moez/QKSMS/manager/PermissionManager.kt | 4 ++-- .../com/moez/QKSMS/feature/compose/ComposeActivity.kt | 6 ++++++ .../java/com/moez/QKSMS/feature/compose/ComposeView.kt | 1 + .../com/moez/QKSMS/feature/compose/ComposeViewModel.kt | 5 +++++ .../main/java/com/moez/QKSMS/feature/main/MainActivity.kt | 5 ++++- .../java/com/moez/QKSMS/feature/main/MainViewModel.kt | 8 ++++---- presentation/src/main/res/layout/main_activity.xml | 1 + 11 files changed, 28 insertions(+), 14 deletions(-) diff --git a/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt b/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt index 55c5001e..df98b3b5 100644 --- a/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt @@ -31,11 +31,9 @@ class PermissionManagerImpl @Inject constructor(private val context: Context) : return Telephony.Sms.getDefaultSmsPackage(context) == context.packageName } - override fun hasSmsAndContacts(): Boolean { - return hasSms() && hasContacts() - } + override fun hasReadSms(): Boolean = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PERMISSION_GRANTED - override fun hasSms(): Boolean = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PERMISSION_GRANTED + override fun hasSendSms(): Boolean = ContextCompat.checkSelfPermission(context, Manifest.permission.SEND_SMS) == PERMISSION_GRANTED override fun hasContacts(): Boolean = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PERMISSION_GRANTED diff --git a/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt b/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt index 4e7befd2..052c13ac 100644 --- a/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt @@ -66,7 +66,7 @@ class CursorToConversationImpl @Inject constructor( } override fun getConversationsCursor(lastSync: Long): Cursor? { - return when (permissionManager.hasSms()) { + return when (permissionManager.hasReadSms()) { true -> context.contentResolver.query(URI, PROJECTION, "date > $lastSync", null, "date desc") diff --git a/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt b/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt index bc16c5ca..46979389 100644 --- a/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/mapper/CursorToMessageImpl.kt @@ -141,7 +141,7 @@ class CursorToMessageImpl @Inject constructor( false -> this.projection } - return when (permissionManager.hasSms()) { + return when (permissionManager.hasReadSms()) { true -> SqliteWrapper.query(context, uri, projection, sortOrder = "normalized_date desc") false -> null } diff --git a/data/src/main/java/com/moez/QKSMS/mapper/CursorToRecipientImpl.kt b/data/src/main/java/com/moez/QKSMS/mapper/CursorToRecipientImpl.kt index bb652cb5..ed4d0387 100644 --- a/data/src/main/java/com/moez/QKSMS/mapper/CursorToRecipientImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/mapper/CursorToRecipientImpl.kt @@ -44,7 +44,7 @@ class CursorToRecipientImpl @Inject constructor( } override fun getRecipientCursor(): Cursor? { - return when (permissionManager.hasSms()) { + return when (permissionManager.hasReadSms()) { true -> context.contentResolver.query(URI, null, null, null, null) false -> null } diff --git a/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt b/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt index 90ea418f..0fd6123a 100644 --- a/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt +++ b/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt @@ -22,9 +22,9 @@ interface PermissionManager { fun isDefaultSms(): Boolean - fun hasSmsAndContacts(): Boolean + fun hasReadSms(): Boolean - fun hasSms(): Boolean + fun hasSendSms(): Boolean fun hasContacts(): Boolean diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt index d7aa27f1..9c11d55b 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt @@ -248,6 +248,12 @@ class ComposeActivity : QkThemedActivity(), ComposeView { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 0) } + override fun requestSmsPermission() { + ActivityCompat.requestPermissions(this, arrayOf( + Manifest.permission.READ_SMS, + Manifest.permission.SEND_SMS), 0) + } + override fun requestDatePicker() { val calendar = Calendar.getInstance() DatePickerDialog(this, DatePickerDialog.OnDateSetListener { _, year, month, day -> diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeView.kt index 572fbae4..a75b3178 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeView.kt @@ -60,6 +60,7 @@ interface ComposeView : QkView { fun clearSelection() fun showDetails(details: String) fun requestStoragePermission() + fun requestSmsPermission() fun requestCamera() fun requestGallery() fun requestDatePicker() diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt index 10fabf24..50bf3512 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt @@ -571,6 +571,11 @@ class ComposeViewModel @Inject constructor( // Send a message when the send button is clicked, and disable editing mode if it's enabled view.sendIntent + .filter { + val hasPermission = permissionManager.hasSendSms() + if (!hasPermission) view.requestSmsPermission() + hasPermission + } .withLatestFrom(view.textChangedIntent) { _, body -> body } .map { body -> body.toString() } .withLatestFrom(state, attachments, conversation, selectedContacts) { body, state, attachments, conversation, contacts -> diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt index 1da3a5ed..2e65c9ca 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt @@ -281,7 +281,10 @@ class MainActivity : QkThemedActivity(), MainView { } override fun requestPermissions() { - ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS), 0) + ActivityCompat.requestPermissions(this, arrayOf( + Manifest.permission.READ_CONTACTS, + Manifest.permission.READ_SMS, + Manifest.permission.SEND_SMS), 0) } override fun clearSearch() { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt index d7b90921..9e4759d0 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt @@ -103,7 +103,7 @@ class MainViewModel @Inject constructor( // If we have all permissions and we've never run a sync, run a sync. This will be the case // when upgrading from 2.7.3, or if the app's data was cleared val lastSync = Realm.getDefaultInstance().use { realm -> realm.where(SyncLog::class.java)?.max("date") ?: 0 } - if (lastSync == 0 && permissionManager.isDefaultSms() && permissionManager.hasSmsAndContacts()) { + if (lastSync == 0 && permissionManager.isDefaultSms() && permissionManager.hasReadSms() && permissionManager.hasContacts()) { syncMessages.execute(Unit) } @@ -114,14 +114,14 @@ class MainViewModel @Inject constructor( override fun bindView(view: MainView) { super.bindView(view) - if (!permissionManager.hasSmsAndContacts()) { + if (!permissionManager.hasReadSms() || !permissionManager.hasContacts()) { view.requestPermissions() } // If the default SMS state or permission states change, update the ViewState Observables.combineLatest( view.activityResumedIntent.map { permissionManager.isDefaultSms() }.distinctUntilChanged(), - view.activityResumedIntent.map { permissionManager.hasSms() }.distinctUntilChanged(), + view.activityResumedIntent.map { permissionManager.hasReadSms() }.distinctUntilChanged(), view.activityResumedIntent.map { permissionManager.hasContacts() }.distinctUntilChanged()) { defaultSms, smsPermission, contactPermission -> newState { copy(defaultSms = defaultSms, smsPermission = smsPermission, contactPermission = contactPermission) } @@ -131,7 +131,7 @@ class MainViewModel @Inject constructor( // If the SMS permission state changes from false to true, sync messages view.activityResumedIntent - .map { permissionManager.hasSms() } + .map { permissionManager.hasReadSms() } .distinctUntilChanged() .skip(1) .filter { hasSms -> hasSms } diff --git a/presentation/src/main/res/layout/main_activity.xml b/presentation/src/main/res/layout/main_activity.xml index 2ec83aee..f1a43d5d 100644 --- a/presentation/src/main/res/layout/main_activity.xml +++ b/presentation/src/main/res/layout/main_activity.xml @@ -135,6 +135,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" + android:layout_marginTop="2dp" android:paddingBottom="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/snackbarButton"