Merge pull request #31 from SimpleMobileTools/master

upd
This commit is contained in:
solokot 2020-05-05 02:08:42 +03:00 committed by GitHub
commit 12cc7f745c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 398 additions and 154 deletions

View file

@ -1,6 +1,21 @@
Changelog
==========
Version 6.10.1 *(2020-05-04)*
----------------------------
* Show the multi-SIM picker only if the app is set as the default dialer
* Added a couple other stability and UX improvements
Version 6.10.0 *(2020-05-03)*
----------------------------
* Adding a first implementation of a Dialer, to really allow the app handle calls
* Increased the minimal required Android OS version to 6 Marshmallow to allow handling calls
* Try fixing the glitch with some saved contacts disappearing
* Properly handle inserting bigger resolution contact images in some cases
* Added a few other UX and UI improvements here and there
Version 6.9.0 *(2020-04-16)*
----------------------------

View file

@ -17,8 +17,8 @@ android {
applicationId "com.simplemobiletools.contacts.pro"
minSdkVersion 23
targetSdkVersion 29
versionCode 60
versionName "6.9.0"
versionCode 62
versionName "6.10.1"
setProperty("archivesBaseName", "contacts")
}
@ -57,7 +57,7 @@ android {
}
dependencies {
implementation 'com.simplemobiletools:commons:5.27.2'
implementation 'com.simplemobiletools:commons:5.27.5'
implementation 'joda-time:joda-time:2.10.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'com.googlecode.ez-vcard:ez-vcard:0.10.5'

View file

@ -15,7 +15,9 @@
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.telecom.action.CONFIGURE_PHONE_ACCOUNT" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
@ -278,10 +280,13 @@
</intent-filter>
</service>
<receiver android:name=".receivers.CallActionReceiver">
<receiver
android:name=".receivers.CallActionReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.simplemobiletools.contacts.action.ACCEPT_CALL"/>
<action android:name="com.simplemobiletools.contacts.action.DECLINE_CALL"/>
<action android:name="com.simplemobiletools.contacts.action.ACCEPT_CALL" />
<action android:name="com.simplemobiletools.contacts.action.DECLINE_CALL" />
</intent-filter>
</receiver>

View file

@ -16,19 +16,23 @@ import android.util.Size
import android.view.WindowManager
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.helpers.MINUTE_SECONDS
import com.simplemobiletools.commons.helpers.isOreoMr1Plus
import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.addCharacter
import com.simplemobiletools.contacts.pro.extensions.audioManager
import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.startCallIntent
import com.simplemobiletools.contacts.pro.helpers.ACCEPT_CALL
import com.simplemobiletools.contacts.pro.helpers.CallManager
import com.simplemobiletools.contacts.pro.helpers.DECLINE_CALL
import com.simplemobiletools.contacts.pro.models.CallContact
import com.simplemobiletools.contacts.pro.receivers.CallActionReceiver
import kotlinx.android.synthetic.main.activity_call.*
import kotlinx.android.synthetic.main.dialpad.*
import java.util.*
class CallActivity : SimpleActivity() {
@ -51,11 +55,17 @@ class CallActivity : SimpleActivity() {
updateTextColors(call_holder)
initButtons()
callContact = CallManager.getCallContact(applicationContext)
callContactAvatar = getCallContactAvatar()
audioManager.mode = AudioManager.MODE_IN_CALL
CallManager.getCallContact(applicationContext) { contact ->
callContact = contact
callContactAvatar = getCallContactAvatar()
runOnUiThread {
setupNotification()
updateOtherPersonsInfo()
}
}
addLockScreenFlags()
setupNotification()
updateOtherPersonsInfo()
initProximitySensor()
CallManager.registerCallback(callCallback)
@ -118,7 +128,30 @@ class CallActivity : SimpleActivity() {
endCall()
}
dialpad_0_holder.setOnClickListener { dialpadPressed('0') }
dialpad_1.setOnClickListener { dialpadPressed('1') }
dialpad_2.setOnClickListener { dialpadPressed('2') }
dialpad_3.setOnClickListener { dialpadPressed('3') }
dialpad_4.setOnClickListener { dialpadPressed('4') }
dialpad_5.setOnClickListener { dialpadPressed('5') }
dialpad_6.setOnClickListener { dialpadPressed('6') }
dialpad_7.setOnClickListener { dialpadPressed('7') }
dialpad_8.setOnClickListener { dialpadPressed('8') }
dialpad_9.setOnClickListener { dialpadPressed('9') }
dialpad_0_holder.setOnLongClickListener { dialpadPressed('+'); true }
dialpad_asterisk.setOnClickListener { dialpadPressed('*') }
dialpad_hashtag.setOnClickListener { dialpadPressed('#') }
dialpad_wrapper.setBackgroundColor(config.backgroundColor)
arrayOf(call_toggle_microphone, call_toggle_speaker, call_dialpad, dialpad_close).forEach {
it.applyColorFilter(config.textColor)
}
}
private fun dialpadPressed(char: Char) {
CallManager.keypad(char)
dialpad_input.addCharacter(char)
}
private fun toggleSpeaker() {
@ -148,8 +181,7 @@ class CallActivity : SimpleActivity() {
return
}
val callContact = CallManager.getCallContact(applicationContext) ?: return
caller_name_label.text = if (callContact.name.isNotEmpty()) callContact.name else getString(R.string.unknown_caller)
caller_name_label.text = if (callContact!!.name.isNotEmpty()) callContact!!.name else getString(R.string.unknown_caller)
if (callContactAvatar != null) {
caller_avatar.setImageBitmap(callContactAvatar)
@ -161,7 +193,7 @@ class CallActivity : SimpleActivity() {
Call.STATE_RINGING -> callRinging()
Call.STATE_ACTIVE -> callStarted()
Call.STATE_DISCONNECTED -> endCall()
Call.STATE_CONNECTING -> initOutgoingCallUI()
Call.STATE_CONNECTING, Call.STATE_DIALING -> initOutgoingCallUI()
Call.STATE_SELECT_PHONE_ACCOUNT -> showPhoneAccountPicker()
}
@ -198,32 +230,14 @@ class CallActivity : SimpleActivity() {
private fun callStarted() {
incoming_call_holder.beGone()
ongoing_call_holder.beVisible()
audioManager.mode = AudioManager.MODE_IN_CALL
callTimer.scheduleAtFixedRate(getCallTimerUpdateTask(), 1000, 1000)
}
@SuppressLint("MissingPermission")
private fun showPhoneAccountPicker() {
if (!hasPermission(PERMISSION_READ_PHONE_STATE)) {
return
}
val items = ArrayList<RadioItem>()
telecomManager.callCapablePhoneAccounts.forEachIndexed { index, account ->
val phoneAccount = telecomManager.getPhoneAccount(account)
var label = phoneAccount.label.toString()
var address = phoneAccount.address.toString()
if (address.startsWith("tel:") && address.substringAfter("tel:").isNotEmpty()) {
address = Uri.decode(address.substringAfter("tel:"))
label += " ($address)"
}
val radioItem = RadioItem(index, label, phoneAccount.accountHandle)
items.add(radioItem)
}
RadioGroupDialog(this, items, titleId = R.string.select_sim) {
if (callContact == null || callContact!!.number.isEmpty()) {
toast(R.string.unknown_error_occurred)
} else {
startCallIntent(callContact!!.number)
}
}
@ -303,6 +317,7 @@ class CallActivity : SimpleActivity() {
val name = "call_notification_channel"
NotificationChannel(channelId, name, importance).apply {
setSound(null, null)
notificationManager.createNotificationChannel(this)
}
}
@ -348,6 +363,7 @@ class CallActivity : SimpleActivity() {
.setCategory(Notification.CATEGORY_CALL)
.setCustomContentView(collapsedView)
.setOngoing(true)
.setSound(null)
.setUsesChronometer(callState == Call.STATE_ACTIVE)
.setChannelId(channelId)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())

View file

@ -31,7 +31,7 @@ abstract class ContactActivity : SimpleActivity() {
protected var currentContactPhotoPath = ""
fun showPhotoPlaceholder(photoView: ImageView) {
val placeholder = BitmapDrawable(resources, getContactLetterIcon(contact?.getNameToDisplay() ?: "S"))
val placeholder = BitmapDrawable(resources, getContactLetterIcon(contact?.getNameToDisplay() ?: "A"))
photoView.setImageDrawable(placeholder)
currentContactPhotoPath = ""
contact?.photo = null

View file

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.telecom.PhoneAccount
import android.telecom.TelecomManager
import android.view.Menu
import com.simplemobiletools.commons.extensions.isDefaultDialer
@ -13,6 +12,7 @@ import com.simplemobiletools.commons.extensions.telecomManager
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.REQUEST_CODE_SET_DEFAULT_DIALER
import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.getHandleToUse
class DialerActivity : SimpleActivity() {
private var callNumber: Uri? = null
@ -43,11 +43,13 @@ class DialerActivity : SimpleActivity() {
@SuppressLint("MissingPermission")
private fun initOutgoingCall() {
try {
Bundle().apply {
putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL))
putBoolean(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, false)
putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false)
telecomManager.placeCall(callNumber, this)
getHandleToUse(intent, callNumber.toString()) { handle ->
Bundle().apply {
putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle)
putBoolean(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, false)
putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false)
telecomManager.placeCall(callNumber, this)
}
finish()
}
} catch (e: Exception) {

View file

@ -19,9 +19,7 @@ import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.adapters.ContactsAdapter
import com.simplemobiletools.contacts.pro.dialogs.CallConfirmationDialog
import com.simplemobiletools.contacts.pro.extensions.callContact
import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.startCallIntent
import com.simplemobiletools.contacts.pro.extensions.*
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.helpers.KEY_PHONE
import com.simplemobiletools.contacts.pro.helpers.LOCATION_DIALPAD
@ -45,16 +43,16 @@ class DialpadActivity : SimpleActivity() {
speedDialValues = config.getSpeedDialValues()
dialpad_0_holder.setOnClickListener { dialpadPressed("0", it) }
dialpad_1.setOnClickListener { dialpadPressed("1", it) }
dialpad_2.setOnClickListener { dialpadPressed("2", it) }
dialpad_3.setOnClickListener { dialpadPressed("3", it) }
dialpad_4.setOnClickListener { dialpadPressed("4", it) }
dialpad_5.setOnClickListener { dialpadPressed("5", it) }
dialpad_6.setOnClickListener { dialpadPressed("6", it) }
dialpad_7.setOnClickListener { dialpadPressed("7", it) }
dialpad_8.setOnClickListener { dialpadPressed("8", it) }
dialpad_9.setOnClickListener { dialpadPressed("9", it) }
dialpad_0_holder.setOnClickListener { dialpadPressed('0', it) }
dialpad_1.setOnClickListener { dialpadPressed('1', it) }
dialpad_2.setOnClickListener { dialpadPressed('2', it) }
dialpad_3.setOnClickListener { dialpadPressed('3', it) }
dialpad_4.setOnClickListener { dialpadPressed('4', it) }
dialpad_5.setOnClickListener { dialpadPressed('5', it) }
dialpad_6.setOnClickListener { dialpadPressed('6', it) }
dialpad_7.setOnClickListener { dialpadPressed('7', it) }
dialpad_8.setOnClickListener { dialpadPressed('8', it) }
dialpad_9.setOnClickListener { dialpadPressed('9', it) }
dialpad_1.setOnLongClickListener { speedDial(1); true }
dialpad_2.setOnLongClickListener { speedDial(2); true }
@ -66,9 +64,9 @@ class DialpadActivity : SimpleActivity() {
dialpad_8.setOnLongClickListener { speedDial(8); true }
dialpad_9.setOnLongClickListener { speedDial(9); true }
dialpad_0_holder.setOnLongClickListener { dialpadPressed("+", null); true }
dialpad_asterisk.setOnClickListener { dialpadPressed("*", it) }
dialpad_hashtag.setOnClickListener { dialpadPressed("#", it) }
dialpad_0_holder.setOnLongClickListener { dialpadPressed('+', null); true }
dialpad_asterisk.setOnClickListener { dialpadPressed('*', it) }
dialpad_hashtag.setOnClickListener { dialpadPressed('#', it) }
dialpad_clear_char.setOnClickListener { clearChar(it) }
dialpad_clear_char.setOnLongClickListener { clearInput(); true }
dialpad_call_button.setOnClickListener { initCall() }
@ -130,13 +128,13 @@ class DialpadActivity : SimpleActivity() {
}
}
private fun dialpadPressed(char: String, view: View?) {
dialpad_input.dispatchKeyEvent(getKeyEvent(getCharKeyCode(char)))
private fun dialpadPressed(char: Char, view: View?) {
dialpad_input.addCharacter(char)
view?.performHapticFeedback()
}
private fun clearChar(view: View) {
dialpad_input.dispatchKeyEvent(getKeyEvent(KeyEvent.KEYCODE_DEL))
dialpad_input.dispatchKeyEvent(dialpad_input.getKeyEvent(KeyEvent.KEYCODE_DEL))
view.performHapticFeedback()
}
@ -144,24 +142,6 @@ class DialpadActivity : SimpleActivity() {
dialpad_input.setText("")
}
private fun getKeyEvent(keyCode: Int) = KeyEvent(0, 0, KeyEvent.ACTION_DOWN, keyCode, 0)
private fun getCharKeyCode(char: String) = when (char) {
"0" -> KeyEvent.KEYCODE_0
"1" -> KeyEvent.KEYCODE_1
"2" -> KeyEvent.KEYCODE_2
"3" -> KeyEvent.KEYCODE_3
"4" -> KeyEvent.KEYCODE_4
"5" -> KeyEvent.KEYCODE_5
"6" -> KeyEvent.KEYCODE_6
"7" -> KeyEvent.KEYCODE_7
"8" -> KeyEvent.KEYCODE_8
"9" -> KeyEvent.KEYCODE_9
"*" -> KeyEvent.KEYCODE_STAR
"+" -> KeyEvent.KEYCODE_PLUS
else -> KeyEvent.KEYCODE_POUND
}
private fun disableKeyboardPopping() {
dialpad_input.showSoftInputOnFocus = false
}

View file

@ -0,0 +1,47 @@
package com.simplemobiletools.contacts.pro.dialogs
import android.annotation.SuppressLint
import android.telecom.PhoneAccountHandle
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.RadioGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.getAvailableSIMCardLabels
import kotlinx.android.synthetic.main.dialog_select_sim.view.*
@SuppressLint("MissingPermission")
class SelectSIMDialog(val activity: BaseSimpleActivity, val phoneNumber: String, val callback: (handle: PhoneAccountHandle) -> Unit) {
private var dialog: AlertDialog? = null
private val view = activity.layoutInflater.inflate(R.layout.dialog_select_sim, null)
init {
val radioGroup = view.select_sim_radio_group
activity.getAvailableSIMCardLabels().forEachIndexed { index, SIMAccount ->
val radioButton = (activity.layoutInflater.inflate(R.layout.radio_button, null) as RadioButton).apply {
text = SIMAccount.label
id = index
setOnClickListener { selectedSIM(SIMAccount.handle, SIMAccount.label) }
}
radioGroup!!.addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
}
dialog = AlertDialog.Builder(activity)
.create().apply {
activity.setupDialogStuff(view, this)
}
}
private fun selectedSIM(handle: PhoneAccountHandle, label: String) {
if (view.select_sim_remember.isChecked) {
activity.config.saveCustomSIM(phoneNumber, label)
}
callback(handle)
dialog?.dismiss()
}
}

View file

@ -1,24 +1,45 @@
package com.simplemobiletools.contacts.pro.extensions
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.telecom.PhoneAccount
import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.PERMISSION_CALL_PHONE
import com.simplemobiletools.commons.helpers.PERMISSION_READ_PHONE_STATE
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.contacts.pro.BuildConfig
import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.dialogs.CallConfirmationDialog
import com.simplemobiletools.contacts.pro.dialogs.SelectSIMDialog
import com.simplemobiletools.contacts.pro.helpers.*
import com.simplemobiletools.contacts.pro.models.Contact
fun SimpleActivity.startCallIntent(recipient: String) {
if (isDefaultDialer()) {
getHandleToUse(null, recipient) { handle ->
launchCallIntent(recipient, handle)
}
} else {
launchCallIntent(recipient, null)
}
}
fun SimpleActivity.launchCallIntent(recipient: String, handle: PhoneAccountHandle?) {
handlePermission(PERMISSION_CALL_PHONE) {
val action = if (it) Intent.ACTION_CALL else Intent.ACTION_DIAL
Intent(action).apply {
data = Uri.fromParts("tel", recipient, null)
if (handle != null) {
putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle)
}
if (resolveActivity(packageManager) != null) {
startActivity(this)
} else {
@ -109,3 +130,28 @@ fun SimpleActivity.callContact(contact: Contact) {
toast(R.string.no_phone_number_found)
}
}
// used at devices with multiple SIM cards
@SuppressLint("MissingPermission")
fun SimpleActivity.getHandleToUse(intent: Intent?, phoneNumber: String, callback: (PhoneAccountHandle) -> Unit) {
handlePermission(PERMISSION_READ_PHONE_STATE) {
if (it) {
val defaultHandle = telecomManager.getDefaultOutgoingPhoneAccount(PhoneAccount.SCHEME_TEL)
when {
intent?.hasExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE) == true -> callback(intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE)!!)
config.getCustomSIM(phoneNumber)?.isNotEmpty() == true -> {
val storedLabel = Uri.decode(config.getCustomSIM(phoneNumber))
val availableSIMs = getAvailableSIMCardLabels()
val firstornull = availableSIMs.firstOrNull { it.label == storedLabel }?.handle ?: availableSIMs.first().handle
callback(firstornull)
}
defaultHandle != null -> callback(defaultHandle)
else -> {
SelectSIMDialog(this, phoneNumber) { handle ->
callback(handle)
}
}
}
}
}
}

View file

@ -1,5 +1,6 @@
package com.simplemobiletools.contacts.pro.extensions
import android.annotation.SuppressLint
import android.content.Context
import android.content.Context.AUDIO_SERVICE
import android.content.Intent
@ -12,6 +13,7 @@ import android.provider.ContactsContract
import androidx.core.content.FileProvider
import com.simplemobiletools.commons.extensions.getIntValue
import com.simplemobiletools.commons.extensions.hasPermission
import com.simplemobiletools.commons.extensions.telecomManager
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CONTACTS
@ -26,6 +28,7 @@ import com.simplemobiletools.contacts.pro.interfaces.GroupsDao
import com.simplemobiletools.contacts.pro.models.Contact
import com.simplemobiletools.contacts.pro.models.ContactSource
import com.simplemobiletools.contacts.pro.models.Organization
import com.simplemobiletools.contacts.pro.models.SIMAccount
import java.io.File
val Context.config: Config get() = Config.newInstance(applicationContext)
@ -326,3 +329,20 @@ fun Context.getAllContactSources(): ArrayList<ContactSource> {
}
fun Context.getPrivateContactSource() = ContactSource(SMT_PRIVATE, SMT_PRIVATE, getString(R.string.phone_storage_hidden))
@SuppressLint("MissingPermission")
fun Context.getAvailableSIMCardLabels(): ArrayList<SIMAccount> {
val SIMAccounts = ArrayList<SIMAccount>()
telecomManager.callCapablePhoneAccounts.forEach { account ->
val phoneAccount = telecomManager.getPhoneAccount(account)
var label = phoneAccount.label.toString()
var address = phoneAccount.address.toString()
if (address.startsWith("tel:") && address.substringAfter("tel:").isNotEmpty()) {
address = Uri.decode(address.substringAfter("tel:"))
label += " ($address)"
}
val SIM = SIMAccount(phoneAccount.accountHandle, label)
SIMAccounts.add(SIM)
}
return SIMAccounts
}

View file

@ -0,0 +1,26 @@
package com.simplemobiletools.contacts.pro.extensions
import android.view.KeyEvent
import android.widget.EditText
fun EditText.addCharacter(char: Char) {
dispatchKeyEvent(getKeyEvent(getCharKeyCode(char)))
}
fun EditText.getKeyEvent(keyCode: Int) = KeyEvent(0, 0, KeyEvent.ACTION_DOWN, keyCode, 0)
private fun getCharKeyCode(char: Char) = when (char) {
'0' -> KeyEvent.KEYCODE_0
'1' -> KeyEvent.KEYCODE_1
'2' -> KeyEvent.KEYCODE_2
'3' -> KeyEvent.KEYCODE_3
'4' -> KeyEvent.KEYCODE_4
'5' -> KeyEvent.KEYCODE_5
'6' -> KeyEvent.KEYCODE_6
'7' -> KeyEvent.KEYCODE_7
'8' -> KeyEvent.KEYCODE_8
'9' -> KeyEvent.KEYCODE_9
'*' -> KeyEvent.KEYCODE_STAR
'+' -> KeyEvent.KEYCODE_PLUS
else -> KeyEvent.KEYCODE_POUND
}

View file

@ -85,11 +85,16 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
updateTextColor(color)
}
}
letter_fastscroller?.textColor = color.getColorStateList()
}
fun primaryColorChanged() {
fragment_fastscroller?.updatePrimaryColor()
fragment_fastscroller?.updateBubblePrimaryColor()
letter_fastscroller_thumb?.thumbColor = config.primaryColor.getColorStateList()
letter_fastscroller_thumb?.textColor = config.primaryColor.getContrastColor()
(fragment_list.adapter as? ContactsAdapter)?.apply {
adjustedPrimaryColor = context.getAdjustedPrimaryColor()
}

View file

@ -7,6 +7,8 @@ import android.telecom.Call
import android.telecom.VideoProfile
import com.simplemobiletools.commons.extensions.getNameFromPhoneNumber
import com.simplemobiletools.commons.extensions.getPhotoUriFromPhoneNumber
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.contacts.pro.extensions.contactsDB
import com.simplemobiletools.contacts.pro.models.CallContact
// inspired by https://github.com/Chooloo/call_manage
@ -45,20 +47,41 @@ class CallManager {
call!!.state
}
fun getCallContact(context: Context): CallContact? {
val callContact = CallContact("", "")
if (call == null) {
return callContact
fun keypad(c: Char) {
call?.playDtmfTone(c)
call?.stopDtmfTone()
}
fun getCallContact(context: Context, callback: (CallContact?) -> Unit) {
val callContact = CallContact("", "", "")
if (call == null || call!!.details == null || call!!.details!!.handle == null) {
callback(callContact)
return
}
val uri = Uri.decode(call!!.details.handle.toString())
if (uri.startsWith("tel:")) {
val number = uri.substringAfter("tel:")
callContact.number = number
callContact.name = context.getNameFromPhoneNumber(number)
callContact.photoUri = context.getPhotoUriFromPhoneNumber(number)
}
return callContact
if (callContact.name == callContact.number) {
ensureBackgroundThread {
val localContact = context.contactsDB.getContactWithNumber("%$number%")
if (localContact != null) {
val storedGroups = ContactsHelper(context).getStoredGroupsSync()
val newContact = LocalContactsHelper(context).convertLocalContactToContact(localContact, storedGroups)
callContact.name = newContact!!.getNameToDisplay()
callContact.photoUri = newContact.photoUri
}
callback(callContact)
}
} else {
callback(callContact)
}
}
}
}
}

View file

@ -1,6 +1,7 @@
package com.simplemobiletools.contacts.pro.helpers
import android.content.Context
import android.net.Uri
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.commons.helpers.BaseConfig
@ -72,6 +73,12 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getString(SPEED_DIAL, "")!!
set(speedDial) = prefs.edit().putString(SPEED_DIAL, speedDial).apply()
fun saveCustomSIM(number: String, SIMlabel: String) {
prefs.edit().putString(REMEMBER_SIM_PREFIX + number, Uri.encode(SIMlabel)).apply()
}
fun getCustomSIM(number: String) = prefs.getString(REMEMBER_SIM_PREFIX + number, "")
fun getSpeedDialValues(): ArrayList<SpeedDial> {
val speedDialType = object : TypeToken<List<SpeedDial>>() {}.type
val speedDialValues = Gson().fromJson<ArrayList<SpeedDial>>(speedDial, speedDialType) ?: ArrayList(1)

View file

@ -24,6 +24,7 @@ const val SHOW_DIALPAD_LETTERS = "show_dialpad_letters"
const val SPEED_DIAL = "speed_dial"
const val LAST_EXPORT_PATH = "last_export_path"
const val WAS_LOCAL_ACCOUNT_INITIALIZED = "was_local_account_initialized"
const val REMEMBER_SIM_PREFIX = "remember_sim_"
const val CONTACT_ID = "contact_id"
const val SMT_PRIVATE = "smt_private" // used at the contact source of local contacts hidden from other apps
@ -56,8 +57,8 @@ const val GROUPS_TAB_MASK = 8
const val ALL_TABS_MASK = CONTACTS_TAB_MASK or FAVORITES_TAB_MASK or GROUPS_TAB_MASK
val tabsList = arrayListOf(CONTACTS_TAB_MASK,
FAVORITES_TAB_MASK,
GROUPS_TAB_MASK
FAVORITES_TAB_MASK,
GROUPS_TAB_MASK
)
// contact photo changes

View file

@ -81,7 +81,7 @@ class LocalContactsHelper(val context: Context) {
return scaledSizePhotoData
}
private fun convertLocalContactToContact(localContact: LocalContact?, storedGroups: ArrayList<Group>): Contact? {
fun convertLocalContactToContact(localContact: LocalContact?, storedGroups: ArrayList<Group>): Contact? {
if (localContact == null) {
return null
}

View file

@ -14,6 +14,9 @@ interface ContactsDao {
@Query("SELECT * FROM contacts WHERE id = :id")
fun getContactWithId(id: Int): LocalContact?
@Query("SELECT * FROM contacts WHERE phone_numbers LIKE :number")
fun getContactWithNumber(number: String): LocalContact?
@Query("UPDATE contacts SET starred = :isStarred WHERE id = :id")
fun updateStarred(isStarred: Int, id: Int)

View file

@ -1,4 +1,4 @@
package com.simplemobiletools.contacts.pro.models
// a simpler Contact model containing just info needed at the call screen
data class CallContact(var name: String, var photoUri: String)
data class CallContact(var name: String, var photoUri: String, var number: String)

View file

@ -0,0 +1,5 @@
package com.simplemobiletools.contacts.pro.models
import android.telecom.PhoneAccountHandle
data class SIMAccount(val handle: PhoneAccountHandle, val label: String)

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/select_sim_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/select_sim_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="@dimen/small_margin"
android:paddingBottom="@dimen/activity_margin"
android:text="@string/select_sim"
android:textSize="@dimen/normal_text_size" />
<RadioGroup
android:id="@+id/select_sim_radio_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/small_margin" />
<include layout="@layout/divider" />
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
android:id="@+id/select_sim_remember"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/small_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingBottom="@dimen/activity_margin"
android:text="@string/always_use_this_sim" />
</LinearLayout>

View file

@ -7,6 +7,7 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:focusableInTouchMode="true"
android:paddingBottom="@dimen/normal_margin"
tools:ignore="HardcodedText">
<com.simplemobiletools.commons.views.MyTextView

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Αποδοχή</string>
<string name="decline">Απόρριψη</string>
<string name="unknown_caller">Άγνωστος</string>
<string name="is_calling">Καλεί</string>
<string name="dialing">Πληκτρολόγηση</string>
<string name="is_calling">Καλεί</string>
<string name="dialing">Πληκτρολόγηση</string>
<string name="call_ended">Τέλος Κλήσης</string>
<string name="call_ending">Τερματισμός Κλήσης</string>
<string name="ongoing_call">Τρέχουσα κλήση</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Принять</string>
<string name="decline">Отклонить</string>
<string name="unknown_caller">Неизвестный абонент</string>
<string name="is_calling">Вызывает</string>
<string name="dialing">Набор номера</string>
<string name="is_calling">Вызывает</string>
<string name="dialing">Набор номера</string>
<string name="call_ended">Вызов завершён</string>
<string name="call_ending">Завершение вызова</string>
<string name="ongoing_call">Текущий вызов</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Prijať</string>
<string name="decline">Odmietnuť</string>
<string name="unknown_caller">Neznámy volajúci</string>
<string name="is_calling">Vám volá</string>
<string name="dialing">Vytáčanie</string>
<string name="is_calling">Vám volá</string>
<string name="dialing">Vytáčanie</string>
<string name="call_ended">Hovor ukončený</string>
<string name="call_ending">Hovor končí</string>
<string name="ongoing_call">Prebiehajúci hovor</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Kabul Et</string>
<string name="decline">Reddet</string>
<string name="unknown_caller">Bilinmeyen Arama</string>
<string name="is_calling">Arıyor</string>
<string name="dialing">Çevriliyor</string>
<string name="is_calling">Arıyor</string>
<string name="dialing">Çevriliyor</string>
<string name="call_ended">Arama Sonlandırıldı</string>
<string name="call_ending">Arama Sonlandırılıyor</string>
<string name="ongoing_call">Devam Eden Arama</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -106,8 +106,8 @@
<string name="accept">Accept</string>
<string name="decline">Decline</string>
<string name="unknown_caller">Unknown Caller</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="is_calling">Is Calling</string>
<string name="dialing">Dialing</string>
<string name="call_ended">Call Ended</string>
<string name="call_ending">Call Ending</string>
<string name="ongoing_call">Ongoing Call</string>

View file

@ -0,0 +1,5 @@
* Adding a first implementation of a Dialer, to really allow the app handle calls
* Increased the minimal required Android OS version to 6 Marshmallow to allow handling calls
* Try fixing the glitch with some saved contacts disappearing
* Properly handle inserting bigger resolution contact images in some cases
* Added a few other UX and UI improvements here and there

View file

@ -0,0 +1,2 @@
* Show the multi-SIM picker only if the app is set as the default dialer
* Added a couple other stability and UX improvements