From 21714a82c4c0d740aed61238b0a4fa704102bbfd Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 13 Feb 2022 12:51:59 +0200 Subject: [PATCH] Added possibility to use Android contacts --- .../com/tutpro/baresip/AndroidContact.kt | 3 +- .../tutpro/baresip/AndroidContactActivity.kt | 67 +------ .../baresip/AndroidContactListAdapter.kt | 3 +- .../tutpro/baresip/AndroidContactsActivity.kt | 171 ++++++++++++++---- .../com/tutpro/baresip/BaresipService.kt | 22 ++- .../com/tutpro/baresip/CallListAdapter.kt | 23 +-- .../com/tutpro/baresip/CallsActivity.kt | 4 +- .../kotlin/com/tutpro/baresip/ChatActivity.kt | 4 +- .../com/tutpro/baresip/ChatListAdapter.kt | 38 ++-- .../com/tutpro/baresip/ChatsActivity.kt | 2 +- .../com/tutpro/baresip/ConfigActivity.kt | 9 - .../com/tutpro/baresip/ContactActivity.kt | 1 - .../com/tutpro/baresip/ContactsActivity.kt | 5 +- .../kotlin/com/tutpro/baresip/MainActivity.kt | 14 +- .../com/tutpro/baresip/MessageListAdapter.kt | 2 +- .../main/kotlin/com/tutpro/baresip/Utils.kt | 47 ++++- .../res/drawable-anydpi/ic_action_call.xml | 10 + .../res/drawable-anydpi/ic_action_swap.xml | 20 ++ .../main/res/drawable-hdpi/ic_action_call.png | Bin 402 -> 0 bytes .../main/res/drawable-mdpi/ic_action_call.png | Bin 278 -> 0 bytes .../res/drawable-xhdpi/ic_action_call.png | Bin 522 -> 0 bytes .../res/drawable-xxhdpi/ic_action_call.png | Bin 773 -> 0 bytes .../res/drawable-xxxhdpi/ic_action_call.png | Bin 1052 -> 0 bytes app/src/main/res/drawable/call.xml | 4 +- app/src/main/res/drawable/swap_contacts.xml | 5 - .../res/layout/activity_android_contacts.xml | 1 + app/src/main/res/layout/activity_config.xml | 10 - app/src/main/res/layout/activity_main.xml | 2 +- app/src/main/res/menu/swap_contacts_icon.xml | 4 +- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 31 files changed, 267 insertions(+), 208 deletions(-) create mode 100644 app/src/main/res/drawable-anydpi/ic_action_call.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_action_swap.xml delete mode 100644 app/src/main/res/drawable-hdpi/ic_action_call.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_action_call.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_action_call.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_call.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/ic_action_call.png delete mode 100644 app/src/main/res/drawable/swap_contacts.xml diff --git a/app/src/main/kotlin/com/tutpro/baresip/AndroidContact.kt b/app/src/main/kotlin/com/tutpro/baresip/AndroidContact.kt index d6c6ff96..0cc27b39 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AndroidContact.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AndroidContact.kt @@ -1,8 +1,9 @@ package com.tutpro.baresip +import android.net.Uri import java.util.ArrayList -class AndroidContact(val id: Long, var name: String, var color: Int, val thumbnailUri: String?) { +class AndroidContact(val id: Long, var name: String, var color: Int, var thumbnailUri: Uri?) { val uris = ArrayList() diff --git a/app/src/main/kotlin/com/tutpro/baresip/AndroidContactActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AndroidContactActivity.kt index 5faa0818..ae9ce1b4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AndroidContactActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AndroidContactActivity.kt @@ -1,21 +1,16 @@ package com.tutpro.baresip -import android.Manifest import android.app.Activity import android.content.Intent -import android.content.pm.PackageManager +import android.net.Uri import android.os.Bundle import android.view.MenuItem import android.view.View -import android.widget.* -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.cardview.widget.CardView -import androidx.core.app.ActivityCompat -import androidx.core.net.toUri -import com.google.android.material.snackbar.Snackbar -import com.tutpro.baresip.Utils.showSnackBar import com.tutpro.baresip.databinding.ActivityAndroidContactBinding class AndroidContactActivity : AppCompatActivity() { @@ -28,7 +23,6 @@ class AndroidContactActivity : AppCompatActivity() { private lateinit var nameView: TextView private lateinit var ulAdapter: AndroidUriListAdapter private lateinit var aor: String - private lateinit var requestPermissionsLauncher: ActivityResultLauncher> private var index = 0 private var color = 0 @@ -49,7 +43,7 @@ class AndroidContactActivity : AppCompatActivity() { cardImageAvatarView = binding.ImageAvatar nameView = binding.Name - val contact = AndroidContactsActivity.androidContacts[index] + val contact = BaresipService.androidContacts[index] val name = contact.name color = contact.color id = contact.id @@ -69,53 +63,6 @@ class AndroidContactActivity : AppCompatActivity() { } - override fun onStart() { - super.onStart() - requestPermissionsLauncher = - registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {} - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, - grandResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grandResults) - when (requestCode) { - CONTACT_PERMISSION_REQUEST_CODE -> { - var allowed = true - for (res in grandResults) - allowed = allowed && res == PackageManager.PERMISSION_GRANTED - if (!allowed) { - when { - ActivityCompat.shouldShowRequestPermissionRationale(this, - Manifest.permission.READ_CONTACTS) -> { - layout.showSnackBar( - binding.root, - getString(R.string.no_android_contacts), - Snackbar.LENGTH_INDEFINITE, - getString(R.string.ok) - ) { - requestPermissionsLauncher.launch(permissions) - } - } - ActivityCompat.shouldShowRequestPermissionRationale(this, - Manifest.permission.WRITE_CONTACTS) -> { - layout.showSnackBar( - binding.root, - getString(R.string.no_android_contacts), - Snackbar.LENGTH_INDEFINITE, - getString(R.string.ok) - ) { - requestPermissionsLauncher.launch(permissions) - } - } - else -> { - requestPermissionsLauncher.launch(permissions) - } - } - } - } - } - } - override fun onOptionsItemSelected(item: MenuItem): Boolean { if (BaresipService.activities.indexOf("android contact,$aor,$index") == -1) return true @@ -151,10 +98,10 @@ class AndroidContactActivity : AppCompatActivity() { textAvatarView.text = "${name[0]}" } - private fun showImageAvatar(thumbNailUri: String) { + private fun showImageAvatar(thumbNailUri: Uri) { textAvatarView.visibility = View.GONE cardAvatarView.visibility = View.VISIBLE - cardImageAvatarView.setImageURI(thumbNailUri.toUri()) + cardImageAvatarView.setImageURI(thumbNailUri) } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/AndroidContactListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/AndroidContactListAdapter.kt index 7605f44e..e222c3c9 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AndroidContactListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AndroidContactListAdapter.kt @@ -11,7 +11,6 @@ import android.widget.ArrayAdapter import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat.startActivity -import androidx.core.net.toUri class AndroidContactListAdapter(private val ctx: Context, private val rows: ArrayList, @@ -45,7 +44,7 @@ class AndroidContactListAdapter(private val ctx: Context, val thumbNailUri = contact.thumbnailUri if (thumbNailUri != null) { - viewHolder.imageAvatarView.setImageURI(thumbNailUri.toUri()) + viewHolder.imageAvatarView.setImageURI(thumbNailUri) } else { contact.color = Utils.randomColor() viewHolder.textAvatarView.background.setTint(contact.color) diff --git a/app/src/main/kotlin/com/tutpro/baresip/AndroidContactsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AndroidContactsActivity.kt index c9efba80..fd714f1e 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AndroidContactsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AndroidContactsActivity.kt @@ -1,35 +1,64 @@ package com.tutpro.baresip +import android.Manifest import android.app.Activity import android.content.* +import android.content.pm.PackageManager import android.database.Cursor +import android.os.Build import android.os.Bundle import android.os.SystemClock import android.provider.ContactsContract import android.view.Menu import androidx.appcompat.app.AppCompatActivity import android.view.MenuItem +import android.widget.RelativeLayout +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.app.ActivityCompat +import androidx.core.net.toUri +import com.google.android.material.snackbar.Snackbar +import com.tutpro.baresip.Utils.showSnackBar import com.tutpro.baresip.databinding.ActivityAndroidContactsBinding class AndroidContactsActivity : AppCompatActivity() { private lateinit var binding: ActivityAndroidContactsBinding + private lateinit var layout: RelativeLayout private lateinit var clAdapter: AndroidContactListAdapter private lateinit var aor: String private var lastSwap: Long = 0 + private lateinit var permissionsLauncher: ActivityResultLauncher> + private val permissions = arrayOf(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS) public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityAndroidContactsBinding.inflate(layoutInflater) setContentView(binding.root) + layout = binding.AndroidContactsView aor = intent.getStringExtra("aor")!! val listView = binding.androidContacts - getAndroidContacts(this) - clAdapter = AndroidContactListAdapter(this, androidContacts, aor) + permissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> + var allowed = true + permissions.entries.forEach { + allowed = allowed && it.value + } + if (allowed) { + fetchAndroidContacts(this) + clAdapter.notifyDataSetChanged() + } + } + + if (Build.VERSION.SDK_INT >= 23 && !Utils.checkPermissions(this, permissions)) + requestPermissions(permissions, CONTACT_PERMISSION_REQUEST_CODE) + else + fetchAndroidContacts(this) + + clAdapter = AndroidContactListAdapter(this, BaresipService.androidContacts, aor) listView.adapter = clAdapter Utils.addActivity("android contacts,$aor") @@ -45,7 +74,7 @@ class AndroidContactsActivity : AppCompatActivity() { when (item.itemId) { - R.id.swapContactsIcon -> { + R.id.swapIcon -> { if (SystemClock.elapsedRealtime() - lastSwap > 1000) { lastSwap = SystemClock.elapsedRealtime() BaresipService.activities.remove("android contacts,$aor") @@ -76,46 +105,110 @@ class AndroidContactsActivity : AppCompatActivity() { } - private fun getAndroidContacts(ctx: Context) { - val projection = arrayOf(ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME, - ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, - ContactsContract.Data.PHOTO_THUMBNAIL_URI) - val selection = - ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' OR " + - ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'" - Log.d(TAG, "******* selection = /$selection/") - val cur: Cursor? = ctx.contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, - selection, null, null) - val contacts = HashMap() - while (cur != null && cur.moveToNext()) { - val id = cur.getLong(0) - val name = cur.getString(1) // display name - val mime = cur.getString(2) // type of data - val data = cur.getString(3) // data - val thumb = cur.getString(4) // thumbnail - // Log.d(TAG, "****** $id - $name - $mime - $data - $thumb") - val contact = if (contacts.containsKey(id)) - contacts[id]!! - else - AndroidContact(id, name, 0, thumb) - if (mime == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) - contact.uris.add("tel:$data") - else if (mime == ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) - contact.uris.add("sip:$data") - else - continue - if (!contacts.containsKey(id)) - contacts[id] = contact + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, + grandResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grandResults) + when (requestCode) { + CONTACT_PERMISSION_REQUEST_CODE -> { + var allowed = true + for (res in grandResults) + allowed = allowed && res == PackageManager.PERMISSION_GRANTED + if (allowed) { + fetchAndroidContacts(this) + clAdapter.notifyDataSetChanged() + } else { + when { + ActivityCompat.shouldShowRequestPermissionRationale(this, + Manifest.permission.READ_CONTACTS) -> { + layout.showSnackBar( + binding.root, + getString(R.string.no_android_contacts), + Snackbar.LENGTH_INDEFINITE, + getString(R.string.ok) + ) { + permissionsLauncher.launch(permissions) + } + } + ActivityCompat.shouldShowRequestPermissionRationale(this, + Manifest.permission.WRITE_CONTACTS) -> { + layout.showSnackBar( + binding.root, + getString(R.string.no_android_contacts), + Snackbar.LENGTH_INDEFINITE, + getString(R.string.ok) + ) { + permissionsLauncher.launch(permissions) + } + } + else -> { + permissionsLauncher.launch(permissions) + } + } + } + } } - cur?.close() - androidContacts.clear() - for ((_, value) in contacts) - androidContacts.add(value) - return } companion object { - val androidContacts = ArrayList() + + fun fetchAndroidContacts(ctx: Context) { + val projection = arrayOf(ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME, + ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, + ContactsContract.Data.PHOTO_THUMBNAIL_URI) + val selection = + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' OR " + + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'" + val cur: Cursor? = ctx.contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, + selection, null, null) + val contacts = HashMap() + while (cur != null && cur.moveToNext()) { + val id = cur.getLong(0) + val name = cur.getString(1) ?: "" + val mime = cur.getString(2) + val data = cur.getString(3) + val thumb = cur.getString(4)?.toUri() + val contact = if (contacts.containsKey(id)) + contacts[id]!! + else + AndroidContact(id, name, 0, thumb) + if (contact.name == "" && name != "") + contact.name = name + if (contact.thumbnailUri == null && thumb != null) + contact.thumbnailUri = thumb + if (mime == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) + contact.uris.add("tel:${data.filterNot{setOf('-', ' ').contains(it)}}") + else if (mime == ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) + contact.uris.add("sip:$data") + else + continue + if (!contacts.containsKey(id)) + contacts[id] = contact + } + cur?.close() + BaresipService.androidContacts.clear() + for ((_, value) in contacts) + if (value.name != "") + BaresipService.androidContacts.add(value) + return + } + + fun findContact(uri: String): AndroidContact? { + for (c in BaresipService.androidContacts) + for (u in c.uris) + if (Utils.uriMatch(u, uri)) + return c + return null + } + + // Return contact name of uri or uri itself if contact with uri is not found + fun contactName(uri: String): String { + val userPart = Utils.uriUserPart(uri) + return if (Utils.isTelNumber(userPart)) + findContact("tel:$userPart")?.name ?: uri + else + findContact(uri)?.name ?: uri + } + } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 266108e6..922a6d97 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -296,6 +296,7 @@ class BaresipService: Service() { this.registerReceiver(bluetoothReceiver, filter) } + AndroidContactsActivity.fetchAndroidContacts(this) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -648,8 +649,7 @@ class BaresipService: Service() { PendingIntent.getActivity(applicationContext, CALL_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID) - val caller = Utils.friendlyUri(ContactsActivity.contactName(peerUri), - Utils.aorDomain(aor)) + val caller = Utils.friendlyUri(Utils.contactName(peerUri), Utils.aorDomain(aor)) nb.setSmallIcon(R.drawable.ic_stat_call) .setColor(ContextCompat.getColor(this, R.color.colorBaresip)) .setContentIntent(pi) @@ -743,8 +743,7 @@ class BaresipService: Service() { PendingIntent.getActivity(applicationContext, TRANSFER_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID) - val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]), - Utils.aorDomain(aor)) + val target = Utils.friendlyUri(Utils.contactName(ev[1]), Utils.aorDomain(aor)) nb.setSmallIcon(R.drawable.ic_stat_call) .setColor(ContextCompat.getColor(this, R.color.colorBaresip)) .setContentIntent(pi) @@ -820,8 +819,7 @@ class BaresipService: Service() { } if (!Utils.isVisible()) { if (missed) { - val caller = Utils.friendlyUri(ContactsActivity.contactName(call.peerUri), - Utils.aorDomain(aor)) + val caller = Utils.friendlyUri(Utils.contactName(call.peerUri), Utils.aorDomain(aor)) val intent = Intent(applicationContext, MainActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK @@ -927,8 +925,7 @@ class BaresipService: Service() { PendingIntent.getActivity(applicationContext, MESSAGE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT) val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID) - val sender = Utils.friendlyUri(ContactsActivity.contactName(peer), - Utils.aorDomain(ua.account.aor)) + val sender = Utils.friendlyUri(Utils.contactName(peer), Utils.aorDomain(ua.account.aor)) nb.setSmallIcon(R.drawable.ic_stat_message) .setColor(ContextCompat.getColor(this, R.color.colorBaresip)) .setContentIntent(pi) @@ -1111,8 +1108,12 @@ class BaresipService: Service() { } private fun requestAudioFocus(type: Int) { - if (audioFocusRequest != null && audioFocusRequest!!.audioAttributesCompat.contentType == type) - return + if (audioFocusRequest != null) { + if (audioFocusRequest!!.audioAttributesCompat.contentType == type) + return + else + abandonAudioFocus() + } val attributes = AudioAttributesCompat.Builder() .setUsage(AudioAttributesCompat.USAGE_VOICE_COMMUNICATION) .setContentType(type) @@ -1418,6 +1419,7 @@ class BaresipService: Service() { val messageUpdate = MutableLiveData() val registrationUpdate = MutableLiveData() val contacts = ArrayList() + val androidContacts = ArrayList() val chatTexts: MutableMap = mutableMapOf() val activities = mutableListOf() var dnsServers = listOf() diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt index eacae134..272dd511 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt @@ -2,7 +2,6 @@ package com.tutpro.baresip import android.content.Context import android.content.Intent -import android.graphics.BitmapFactory import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,8 +11,6 @@ import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView -import java.util.* - class CallListAdapter(private val ctx: Context, private val aor: String, private val rows: ArrayList) : ArrayAdapter(ctx, R.layout.call_row, rows) { @@ -44,23 +41,7 @@ class CallListAdapter(private val ctx: Context, private val aor: String, private val callRow = rows[position] - val contact = ContactsActivity.findContact(callRow.peerUri) - if (contact != null) { - val avatarImage = contact.avatarImage - if (avatarImage != null) { - viewHolder.imageAvatarView.setImageBitmap(avatarImage) - } else { - viewHolder.textAvatarView.background.setTint(contact.color) - if (contact.name.isNotEmpty()) - viewHolder.textAvatarView.text = "${contact.name[0]}" - else - viewHolder.textAvatarView.text = "" - viewHolder.imageAvatarView.setImageBitmap(Utils.bitmapFromView(viewHolder.textAvatarView)) - } - } else { - val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.person_image) - viewHolder.imageAvatarView.setImageBitmap(bitmap) - } + Utils.setAvatar(ctx, viewHolder.imageAvatarView, viewHolder.textAvatarView, callRow.peerUri) viewHolder.directionsView.removeAllViews() var count = 1 @@ -81,7 +62,7 @@ class CallListAdapter(private val ctx: Context, private val aor: String, private if (count <= 3) viewHolder.etcView.text = "" - val contactName = ContactsActivity.contactName(callRow.peerUri) + val contactName = Utils.contactName(callRow.peerUri) if (contactName.startsWith("sip:")) viewHolder.peerURIView.text = Utils.friendlyUri(contactName, Utils.aorDomain(callRow.aor)) else diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt index 1216c559..ce5f435c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt @@ -50,7 +50,7 @@ class CallsActivity : AppCompatActivity() { listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ -> val peerUri = uaHistory[pos].peerUri - var peerName = ContactsActivity.contactName(peerUri) + var peerName = Utils.contactName(peerUri) if (peerName.startsWith("sip:")) peerName = Utils.friendlyUri(peerName, Utils.aorDomain(aor)) val dialogClickListener = DialogInterface.OnClickListener { _, which -> @@ -95,7 +95,7 @@ class CallsActivity : AppCompatActivity() { listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ -> val peerUri = uaHistory[pos].peerUri - val peerName = ContactsActivity.contactName(peerUri) + val peerName = Utils.contactName(peerUri) val dialogClickListener = DialogInterface.OnClickListener { _, which -> when (which) { DialogInterface.BUTTON_NEGATIVE -> { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt index 4f061c89..62453d07 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt @@ -63,7 +63,7 @@ class ChatActivity : AppCompatActivity() { imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager this@ChatActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) - var chatPeer = ContactsActivity.contactName(peerUri) + var chatPeer = Utils.contactName(peerUri) if (chatPeer.startsWith("sip:")) chatPeer = Utils.friendlyUri(chatPeer, Utils.aorDomain(aor)) @@ -112,7 +112,7 @@ class ChatActivity : AppCompatActivity() { } } val builder = AlertDialog.Builder(this@ChatActivity, R.style.Theme_AppCompat) - if (ContactsActivity.contactName(peerUri) == peerUri) + if (Utils.contactName(peerUri) == peerUri) with (builder) { setMessage(String.format(getString(R.string.long_message_question), chatPeer)) diff --git a/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt index 5ecda967..6d4fa48d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt @@ -1,17 +1,18 @@ package com.tutpro.baresip import android.content.Context -import android.graphics.BitmapFactory import android.graphics.Typeface -import androidx.core.content.ContextCompat import android.text.format.DateUtils.isToday import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.* - -import java.util.* +import android.widget.ArrayAdapter +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.content.ContextCompat import java.text.DateFormat +import java.util.* class ChatListAdapter(private val ctx: Context, private val rows: ArrayList) : ArrayAdapter(ctx, R.layout.message, rows) { @@ -43,26 +44,7 @@ class ChatListAdapter(private val ctx: Context, private val rows: ArrayList { + R.id.swapIcon -> { if (SystemClock.elapsedRealtime() - lastClick > 1000) { lastClick = SystemClock.elapsedRealtime() BaresipService.activities.remove("contacts,$aor") @@ -117,9 +117,10 @@ class ContactsActivity : AppCompatActivity() { } fun findContact(uri: String): Contact? { - for (c in Contact.contacts()) + for (c in Contact.contacts()) { if (Utils.uriMatch(c.uri, uri)) return c + } return null } diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index 3eb0d0a5..90c23900 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -1105,8 +1105,7 @@ class MainActivity : AppCompatActivity() { val call = Call.ofCallp(callp)!! val titleView = View.inflate(this, R.layout.alert_title, null) as TextView titleView.text = getString(R.string.transfer_request) - val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]), - Utils.aorDomain(aor)) + val target = Utils.friendlyUri(Utils.contactName(ev[1]), Utils.aorDomain(aor)) with(AlertDialog.Builder(this)) { setCustomTitle(titleView) setMessage(String.format(getString(R.string.transfer_request_query), @@ -1752,8 +1751,7 @@ class MainActivity : AppCompatActivity() { val latest = NewCallHistory.aorLatestHistory(aor) if (latest != null) callUri.setText( - Utils.friendlyUri( - ContactsActivity.contactName(latest.peerUri), Utils.aorDomain(aor) + Utils.friendlyUri(Utils.contactName(latest.peerUri), Utils.aorDomain(aor) ) ) } @@ -1799,7 +1797,7 @@ class MainActivity : AppCompatActivity() { else getString(R.string.outgoing_call_to_dots) callTimer.visibility = View.INVISIBLE - callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerUri), + callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri), Utils.aorDomain(ua.account.aor))) securityButton.visibility = View.INVISIBLE callButton.visibility = View.INVISIBLE @@ -1814,7 +1812,7 @@ class MainActivity : AppCompatActivity() { "incoming" -> { callTitle.text = getString(R.string.incoming_call_from_dots) callTimer.visibility = View.INVISIBLE - callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerUri), + callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri), Utils.aorDomain(ua.account.aor))) callUri.setAdapter(null) securityButton.visibility = View.INVISIBLE @@ -1834,7 +1832,7 @@ class MainActivity : AppCompatActivity() { } if (call.referTo != "") { callTitle.text = getString(R.string.transferring_call_to_dots) - callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.referTo), + callUri.setText(Utils.friendlyUri(Utils.contactName(call.referTo), Utils.aorDomain(ua.account.aor))) transferButton.isEnabled = false } else { @@ -1842,7 +1840,7 @@ class MainActivity : AppCompatActivity() { callTitle.text = getString(R.string.outgoing_call_to_dots) else callTitle.text = getString(R.string.incoming_call_from_dots) - callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerUri), + callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri), Utils.aorDomain(ua.account.aor))) transferButton.isEnabled = true } diff --git a/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt index 0735acb4..619ab43f 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt @@ -45,7 +45,7 @@ class MessageListAdapter(private val ctx: Context, private val rows: ArrayList + + diff --git a/app/src/main/res/drawable-anydpi/ic_action_swap.xml b/app/src/main/res/drawable-anydpi/ic_action_swap.xml new file mode 100644 index 00000000..eff1e303 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_action_swap.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/app/src/main/res/drawable-hdpi/ic_action_call.png b/app/src/main/res/drawable-hdpi/ic_action_call.png deleted file mode 100644 index 025fd0ee568d295800c2aa8d5002314993b39e30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 402 zcmV;D0d4+?P)r-4|Co(>WM;!^}1gb)08VNWkZZIY6D!L|WsDpTc_%OCY zk?xK`a#ZV}aSYT!deAI>2Ab>S217+V4Jm{=2ZMujk;)`cXgLf9M^z(*(k>tt8)ygd z1MyZQN6iCbj)8WR0T7=+a#SA>vktVQ!jN(u%uyT!s-ReCl)C}3IMs^{pn;iaWz&3+ zMK~N&g{76S2Z)ye@hl*&1Y#~q9mEKA)M>PY?uh1?Y65j33`bBi`c9zvz6(@%lHeE+ zPNQ~0-->3zDH0q*T?Zi*3Dsmcgf0uV*mgE diff --git a/app/src/main/res/drawable-mdpi/ic_action_call.png b/app/src/main/res/drawable-mdpi/ic_action_call.png deleted file mode 100644 index 6bb21bf4407040150e685ddd2fa20e423d2fc55d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 zcmV+x0qOpUP)2HKzs;l zNeHbh@c`n}&}8a_Lk$Z>Nf@X(6)7)-pvehBlQ1aN%>&{pAkF|{D^e_Agj#YM7AH`H zg`i3J3>JKh+~7Kdl)BdAFdU32iTDZl45r8ew0zQsmgA{s0a~%*2Q45ML5q4&eKKdX c>Lv*Q0H>DF%eK?0?EnA(07*qoM6N<$f>L~IbN~PV diff --git a/app/src/main/res/drawable-xhdpi/ic_action_call.png b/app/src/main/res/drawable-xhdpi/ic_action_call.png deleted file mode 100644 index d530af6cde1aaae28eb84350a98e259ffcdf2c0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 522 zcmV+l0`>igP)0DeLqD2L*gWA@%|5LmN zCxpi(d9Tp)4&K3cD7+^3$xANZyLg@p7cN||j3|nZKpoIHMbBy-SAeYK{}qCKjsQJF z0JUz3Bfy6tzzDR$5g;@KP}=4Q@L&OO$Pu7v0Z`=#aBcx`!x5lj0q_Z$=LWEa6~+`| zmm7d@QHg#)8ys(=3xnhbpb}R*5o9FaXPZ0%EP~#}U3m?nk&t{@iml!!s!`RG6p-+( z25`sHLZ<)}h+POI0nC9~8o&!^RT6}HGkP9y;=fZ9Y$c_8gp>Jn~r zPZGp2XsAKFsdt9uan?aQGbzb%(les8s+}kr{=bASc8mjrYdmHVv6*hhK_#e#Ua)!i5X(4>lvS)2&T&O8@`> M07*qoM6N<$f(=^T4FCWD diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_call.png b/app/src/main/res/drawable-xxhdpi/ic_action_call.png deleted file mode 100644 index ae70b7ff275d3dbcb9bc24c4cf42234b1778abc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 773 zcmV+g1N!`lP)@-tEihZ zq%{kGMmYn@TLAQ)GoUx%2Lm{(+?&M|_;*Y=*l6Zl2+m3|;B4R~@3|oAhwkfylk;2= zmDzC}a5A22f}5U-2q){gD7f)1@U6fJ2J`~_Jpj%%xYcuA0HK#6jQ>HJ_C!@kI{|>M zz?}j}sR7L+e@Or-)db!S0EFO%1(H%d;6DM7@TjOoASpGgdE~F)N^>1hGx$VPY7?@G zl=`UIuraC~5J*ZDHKlgW`q(ETpe%S_7uti{U5E5KWD?{j_?7FBM!`2BklHQ%);sVJ z9!otpNcoUp4a=>^;QBetxP8~eoN69CLiu?*$$;>Ue>x=O$Blb1# z!oq$$+8)ug5H{gdS8vkxqU);TYxANvlzO~;AYw=IEe&Q(@gG1 zyou{Z!AUHjnzAX@c?jtaAYTe_B7nm4q*+Ze={6u=e7pUWW%nFkberh3WJh!E<}M%~ ztX?|7y%j+E2D6I>CXQ{FAGe$-Me|7|nsj?G1XSi6%B3jt$9dJB%8U-^Q?65b#i`Ker3EL4yF?<9NF)-8ME3L#wUCZ9{Q?zd00000NkvXXu0mjf Dss3PA diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_call.png b/app/src/main/res/drawable-xxxhdpi/ic_action_call.png deleted file mode 100644 index af221e1d858855e337d573bab3ce022a4c3cf6d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1052 zcmV+%1mpXOP)qilkibPix#D&=eMbJN>8y6Ol7NRZ+QYm56tQ$mMGVAp0G|~A>|i=72ar<&a0%(k0K8QKa2x5$ z0L&@@c#L#q0G=oTm_fQS04XH^pU4p;+!(->CKll8d6OJR!i@n8khc^7l*kv6aAN>b zrS%{T#1;@1l>p?Bt_;9SB>-kgB8G(h&4i4TNVqY8vpi^O07xTY*+9Ia1mFe|mO;oU z?Tj5jx-tNF9fxnGw&#(o96+DL@Hfb#NYx&~lB4hwNHZ9KM-Ivke)&xR7;Iu)2xZ3s zfCxE@vf~%R9h4ov0OGuskFw*j3{9i#_=PacE1C5G%wx+@7s6}7ju*<0B7hOWgS+p^ z2a%QzfPLgQf~#NxY3V^26YLY170<&+O9w!g;3_bFju4NK6MpQh2oW z1Nk@-a}OXQoD~@_kh_tZdkEbYJ7;q^HLnBVq;Nba^Fv>Npa9`I`IiuaS<*P9_+9ps z$I17|S2aItuR)lw=r^&Tacs#vfmh?%R`Z?SkspxHwe5l-FI%TAp055#KI8E7M+GN* zesj4rGqb1WW|4f0!I)CoW15SQkA!l6qiSYUw&<>P*}>-~cyGGdLnPbW;U&+fJD-Ja z3Qb?QlRRbdkDC(lFzDJ5|ME8!50-o-p9U0NFqWfEE=MKH za|GipEIU$v3-jG_+Oiv$0X9=_PoV{6=O2fCb~GWpPpI}6(`jY*Y@~%{r#%4dx>;Kf zaLV5FF}lE4Q=-+s{I&s5wQP|M*zRE7SNLrMplXIRsnn$r04xUQWPp+c0FFWQ@-lT1 z0Q^Dd;*I`g0PqVUwwK3-|7mYwi1!Ri0N}SQjWLJ<0QkL&9^peGMF8*%W0=pZZ32Mb z`-eCmq0K5a8LYXNjr427805AJOUeN9NW3wSK5n&>;e7>{vnafZ#S%u8+pnd#5#b^) zVQ&R!PP>K{{O+I(aEIU&_sX8-uJJj3f5IxiNu|)|!c?Vhm0000 - + diff --git a/app/src/main/res/drawable/swap_contacts.xml b/app/src/main/res/drawable/swap_contacts.xml deleted file mode 100644 index 69851328..00000000 --- a/app/src/main/res/drawable/swap_contacts.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_android_contacts.xml b/app/src/main/res/layout/activity_android_contacts.xml index 652add17..98209afa 100644 --- a/app/src/main/res/layout/activity_android_contacts.xml +++ b/app/src/main/res/layout/activity_android_contacts.xml @@ -1,6 +1,7 @@ - - - + android:icon="@drawable/ic_test_swap" /> diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index c119d9f4..5a244cd9 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -520,7 +520,7 @@ Tallennustila-käyttöoikeutta. Et voi palauttaa sovelluksen tietoja ilman Tallennustila-käyttöoikeutta. - Et voi lisätä tai poistaa Android-yhteystietoja ilman + Et voi käsitellä Androidin yhteystietoja ilman Kontaktit-käyttöoikeutta. Sinulla ei ole yhtään tuettua video-kameraa. Näytä salasana diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2a058811..a92f18cb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -475,7 +475,7 @@ Grant \"Camera\" permission to make or answer video calls. You are not able create backup without \"Storage\" permission. You are not able restore backup without \"Storage\" permission. - You are not able add or remove Android contacts without + You are not able to access Android contacts without \"Contacts\" permission. You don\'t have any supported video cameras. Show Password