Replaced Show Android Contacts setting with Contacts setting with possible
values 'baresip', 'Android', and Both
This commit is contained in:
@ -85,7 +85,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".ContactsActivity"
|
android:name=".ContactsActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
android:label="@string/baresip_contacts"
|
android:label="@string/contacts"
|
||||||
android:parentActivityName=".MainActivity"
|
android:parentActivityName=".MainActivity"
|
||||||
android:windowSoftInputMode="adjustPan" >
|
android:windowSoftInputMode="adjustPan" >
|
||||||
</activity>
|
</activity>
|
||||||
@ -95,18 +95,11 @@
|
|||||||
android:label="@string/contact"
|
android:label="@string/contact"
|
||||||
android:parentActivityName=".ContactsActivity" >
|
android:parentActivityName=".ContactsActivity" >
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
|
||||||
android:name=".AndroidContactsActivity"
|
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
|
||||||
android:label="@string/android_contacts"
|
|
||||||
android:parentActivityName=".MainActivity"
|
|
||||||
android:windowSoftInputMode="adjustPan" >
|
|
||||||
</activity>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".AndroidContactActivity"
|
android:name=".AndroidContactActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
android:label="@string/contact"
|
android:label="@string/contact"
|
||||||
android:parentActivityName=".AndroidContactsActivity" >
|
android:parentActivityName=".ContactsActivity" >
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ConfigActivity"
|
android:name=".ConfigActivity"
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
package com.tutpro.baresip
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class AndroidContact(val id: Long, var name: String, var color: Int, var thumbnailUri: Uri?) {
|
|
||||||
|
|
||||||
val uris = ArrayList<String>()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
fun contacts(): ArrayList<AndroidContact> {
|
|
||||||
return BaresipService.androidContacts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -26,7 +26,6 @@ class AndroidContactActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private var index = 0
|
private var index = 0
|
||||||
private var color = 0
|
private var color = 0
|
||||||
private var id: Long = 0
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
@ -43,10 +42,9 @@ class AndroidContactActivity : AppCompatActivity() {
|
|||||||
cardImageAvatarView = binding.ImageAvatar
|
cardImageAvatarView = binding.ImageAvatar
|
||||||
nameView = binding.Name
|
nameView = binding.Name
|
||||||
|
|
||||||
val contact = BaresipService.androidContacts[index]
|
val contact = Contact.contacts()[index] as Contact.AndroidContact
|
||||||
val name = contact.name
|
val name = contact.name
|
||||||
color = contact.color
|
color = contact.color
|
||||||
id = contact.id
|
|
||||||
val thumbnailUri = contact.thumbnailUri
|
val thumbnailUri = contact.thumbnailUri
|
||||||
if (thumbnailUri != null)
|
if (thumbnailUri != null)
|
||||||
showImageAvatar(thumbnailUri)
|
showImageAvatar(thumbnailUri)
|
||||||
@ -105,5 +103,3 @@ class AndroidContactActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,75 +0,0 @@
|
|||||||
package com.tutpro.baresip
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.SystemClock
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat.startActivity
|
|
||||||
|
|
||||||
class AndroidContactListAdapter(private val ctx: Context,
|
|
||||||
private val rows: ArrayList<AndroidContact>,
|
|
||||||
private val aor: String) :
|
|
||||||
ArrayAdapter<AndroidContact>(ctx, R.layout.android_contact_row, rows) {
|
|
||||||
|
|
||||||
private val layoutInflater = LayoutInflater.from(context)
|
|
||||||
private var lastClick: Long = 0
|
|
||||||
|
|
||||||
private class ViewHolder(view: View?) {
|
|
||||||
val textAvatarView = view?.findViewById(R.id.TextAvatar) as TextView
|
|
||||||
val imageAvatarView = view?.findViewById(R.id.ImageAvatar) as ImageView
|
|
||||||
val nameView = view?.findViewById(R.id.contactName) as TextView
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getView(position: Int, view: View?, parent: ViewGroup): View {
|
|
||||||
|
|
||||||
val viewHolder: ViewHolder
|
|
||||||
val rowView: View
|
|
||||||
|
|
||||||
if (view == null) {
|
|
||||||
rowView = layoutInflater.inflate(R.layout.android_contact_row, parent, false)
|
|
||||||
viewHolder = ViewHolder(rowView)
|
|
||||||
rowView.tag = viewHolder
|
|
||||||
} else {
|
|
||||||
rowView = view
|
|
||||||
viewHolder = rowView.tag as ViewHolder
|
|
||||||
}
|
|
||||||
|
|
||||||
val contact = rows[position]
|
|
||||||
|
|
||||||
val thumbNailUri = contact.thumbnailUri
|
|
||||||
if (thumbNailUri != null) {
|
|
||||||
viewHolder.imageAvatarView.setImageURI(thumbNailUri)
|
|
||||||
} 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))
|
|
||||||
}
|
|
||||||
|
|
||||||
viewHolder.nameView.text = contact.name
|
|
||||||
viewHolder.nameView.textSize = 20f
|
|
||||||
viewHolder.nameView.setPadding(6, 6, 0, 6)
|
|
||||||
|
|
||||||
viewHolder.nameView.setOnClickListener {
|
|
||||||
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
|
||||||
lastClick = SystemClock.elapsedRealtime()
|
|
||||||
val i = Intent(ctx, AndroidContactActivity::class.java)
|
|
||||||
val b = Bundle()
|
|
||||||
b.putString("aor", aor)
|
|
||||||
b.putInt("index", position)
|
|
||||||
i.putExtras(b)
|
|
||||||
startActivity(ctx, i, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowView
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,228 +0,0 @@
|
|||||||
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<Array<String>>
|
|
||||||
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
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
clAdapter = AndroidContactListAdapter(this, BaresipService.androidContacts, aor)
|
|
||||||
listView.adapter = clAdapter
|
|
||||||
|
|
||||||
Utils.addActivity("android contacts,$aor")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.swap_contacts_icon, menu)
|
|
||||||
return super.onCreateOptionsMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
|
|
||||||
when (item.itemId) {
|
|
||||||
|
|
||||||
R.id.swapIcon -> {
|
|
||||||
if (SystemClock.elapsedRealtime() - lastSwap > 1000) {
|
|
||||||
lastSwap = SystemClock.elapsedRealtime()
|
|
||||||
BaresipService.activities.remove("android contacts,$aor")
|
|
||||||
val intent = Intent(this, ContactsActivity::class.java)
|
|
||||||
intent.putExtra("aor", aor)
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
android.R.id.home -> {
|
|
||||||
BaresipService.activities.remove("android contacts,$aor")
|
|
||||||
setResult(Activity.RESULT_OK, Intent())
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
|
|
||||||
BaresipService.activities.remove("android contacts,$aor")
|
|
||||||
setResult(Activity.RESULT_OK, Intent())
|
|
||||||
finish()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
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<Long, AndroidContact>()
|
|
||||||
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, Utils.randomColor(), 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)
|
|
||||||
Utils.reloadContactNames()
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return first sip (preferred) or tel uri of contact name or
|
|
||||||
// null if contact is not found or if it has no uris
|
|
||||||
fun contactUri(name: String): String? {
|
|
||||||
for (c in BaresipService.androidContacts)
|
|
||||||
if (c.name == name) {
|
|
||||||
if (c.uris.isNotEmpty()) {
|
|
||||||
for (u in c.uris)
|
|
||||||
if (u.startsWith("sip:"))
|
|
||||||
return u
|
|
||||||
return c.uris.first()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -41,6 +41,7 @@ import java.io.File
|
|||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ class BaresipService: Service() {
|
|||||||
private var hotSpotIsEnabled = false
|
private var hotSpotIsEnabled = false
|
||||||
private var hotSpotAddresses = mapOf<String, String>()
|
private var hotSpotAddresses = mapOf<String, String>()
|
||||||
private var mediaPlayer: MediaPlayer? = null
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
|
private var contentObserverRegistered = false
|
||||||
|
|
||||||
@SuppressLint("WakelockTimeout")
|
@SuppressLint("WakelockTimeout")
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@ -299,33 +301,28 @@ class BaresipService: Service() {
|
|||||||
this.registerReceiver(bluetoothReceiver, filter)
|
this.registerReceiver(bluetoothReceiver, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
val contentObserver: ContentObserver = object : ContentObserver(null) {
|
contentObserver = object : ContentObserver(null) {
|
||||||
override fun onChange(self: Boolean) {
|
override fun onChange(self: Boolean) {
|
||||||
Log.d(TAG, "Contacts change")
|
Log.d(TAG, "Contacts change")
|
||||||
AndroidContactsActivity.fetchAndroidContacts(this@BaresipService.applicationContext)
|
if (contactsMode != "baresip") {
|
||||||
|
Contact.loadAndroidContacts(this@BaresipService.applicationContext)
|
||||||
|
Contact.contactsUpdate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
AndroidContactsActivity.fetchAndroidContacts(this)
|
|
||||||
contentResolver.registerContentObserver(
|
|
||||||
ContactsContract.Contacts.CONTENT_URI, true, contentObserver)
|
|
||||||
} catch(e: SecurityException) {
|
|
||||||
Log.i(TAG, "No Contacts permission")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
|
||||||
val action: String
|
val action: String?
|
||||||
|
|
||||||
if (intent == null) {
|
if (intent == null) {
|
||||||
action = "Start"
|
action = "Start"
|
||||||
Log.d(TAG, "Received onStartCommand with null intent")
|
Log.d(TAG, "Received onStartCommand with null intent")
|
||||||
} else {
|
} else {
|
||||||
// Utils.dumpIntent(intent)
|
// Utils.dumpIntent(intent)
|
||||||
action = intent.action!!
|
action = intent.action
|
||||||
Log.d(TAG, "Received onStartCommand action $action")
|
Log.d(TAG, "Received onStartCommand action $action")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,13 +356,21 @@ class BaresipService: Service() {
|
|||||||
Log.i(TAG, "Asset '$a' already copied")
|
Log.i(TAG, "Asset '$a' already copied")
|
||||||
}
|
}
|
||||||
if (a == "config")
|
if (a == "config")
|
||||||
Config.initialize()
|
Config.initialize(applicationContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File(filesDir, "history").exists())
|
if (File(filesDir, "history").exists())
|
||||||
File(filesDir, "history").renameTo(File(filesDir, "calls"))
|
File(filesDir, "history").renameTo(File(filesDir, "calls"))
|
||||||
|
|
||||||
Contact.restore()
|
|
||||||
|
if (contactsMode != "Android")
|
||||||
|
Contact.restoreBaresipContacts()
|
||||||
|
if (contactsMode != "baresip") {
|
||||||
|
Contact.loadAndroidContacts(applicationContext)
|
||||||
|
registerContentObserver()
|
||||||
|
}
|
||||||
|
Contact.contactsUpdate()
|
||||||
|
|
||||||
val history = CallHistory.get()
|
val history = CallHistory.get()
|
||||||
if (history.isEmpty()) {
|
if (history.isEmpty()) {
|
||||||
NewCallHistory.restore()
|
NewCallHistory.restore()
|
||||||
@ -417,6 +422,14 @@ class BaresipService: Service() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"Start Content Observer" -> {
|
||||||
|
registerContentObserver()
|
||||||
|
}
|
||||||
|
|
||||||
|
"Stop Content Observer" -> {
|
||||||
|
unRegisterContentObserver()
|
||||||
|
}
|
||||||
|
|
||||||
"Call Answer" -> {
|
"Call Answer" -> {
|
||||||
val uap = intent!!.getStringExtra("uap")!!
|
val uap = intent!!.getStringExtra("uap")!!
|
||||||
val callp = intent.getStringExtra("callp")!!
|
val callp = intent.getStringExtra("callp")!!
|
||||||
@ -666,7 +679,7 @@ class BaresipService: Service() {
|
|||||||
PendingIntent.getActivity(applicationContext, CALL_REQ_CODE, intent,
|
PendingIntent.getActivity(applicationContext, CALL_REQ_CODE, intent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||||
val caller = Utils.friendlyUri(Utils.contactName(peerUri), Utils.aorDomain(aor))
|
val caller = Utils.friendlyUri(Contact.contactName(peerUri), Utils.aorDomain(aor))
|
||||||
nb.setSmallIcon(R.drawable.ic_stat_call)
|
nb.setSmallIcon(R.drawable.ic_stat_call)
|
||||||
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
||||||
.setContentIntent(pi)
|
.setContentIntent(pi)
|
||||||
@ -760,7 +773,7 @@ class BaresipService: Service() {
|
|||||||
PendingIntent.getActivity(applicationContext, TRANSFER_REQ_CODE,
|
PendingIntent.getActivity(applicationContext, TRANSFER_REQ_CODE,
|
||||||
intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||||
val target = Utils.friendlyUri(Utils.contactName(ev[1]), Utils.aorDomain(aor))
|
val target = Utils.friendlyUri(Contact.contactName(ev[1]), Utils.aorDomain(aor))
|
||||||
nb.setSmallIcon(R.drawable.ic_stat_call)
|
nb.setSmallIcon(R.drawable.ic_stat_call)
|
||||||
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
||||||
.setContentIntent(pi)
|
.setContentIntent(pi)
|
||||||
@ -836,7 +849,7 @@ class BaresipService: Service() {
|
|||||||
}
|
}
|
||||||
if (!Utils.isVisible()) {
|
if (!Utils.isVisible()) {
|
||||||
if (missed) {
|
if (missed) {
|
||||||
val caller = Utils.friendlyUri(Utils.contactName(call.peerUri), Utils.aorDomain(aor))
|
val caller = Utils.friendlyUri(Contact.contactName(call.peerUri), Utils.aorDomain(aor))
|
||||||
val intent = Intent(applicationContext, MainActivity::class.java)
|
val intent = Intent(applicationContext, MainActivity::class.java)
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or
|
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or
|
||||||
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
@ -942,7 +955,7 @@ class BaresipService: Service() {
|
|||||||
PendingIntent.getActivity(applicationContext, MESSAGE_REQ_CODE, intent,
|
PendingIntent.getActivity(applicationContext, MESSAGE_REQ_CODE, intent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||||
val sender = Utils.friendlyUri(Utils.contactName(peer), Utils.aorDomain(ua.account.aor))
|
val sender = Utils.friendlyUri(Contact.contactName(peer), Utils.aorDomain(ua.account.aor))
|
||||||
nb.setSmallIcon(R.drawable.ic_stat_message)
|
nb.setSmallIcon(R.drawable.ic_stat_message)
|
||||||
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
||||||
.setContentIntent(pi)
|
.setContentIntent(pi)
|
||||||
@ -1389,6 +1402,24 @@ class BaresipService: Service() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun registerContentObserver() {
|
||||||
|
if (!contentObserverRegistered)
|
||||||
|
try {
|
||||||
|
contentResolver.registerContentObserver(ContactsContract.Contacts.CONTENT_URI,
|
||||||
|
true, contentObserver)
|
||||||
|
contentObserverRegistered = true
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
Log.i(TAG, "No Contacts permission")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unRegisterContentObserver() {
|
||||||
|
if (contentObserverRegistered) {
|
||||||
|
contentResolver.unregisterContentObserver(contentObserver)
|
||||||
|
contentObserverRegistered = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun cleanService() {
|
private fun cleanService() {
|
||||||
am.mode = AudioManager.MODE_NORMAL
|
am.mode = AudioManager.MODE_NORMAL
|
||||||
abandonAudioFocus()
|
abandonAudioFocus()
|
||||||
@ -1429,7 +1460,6 @@ class BaresipService: Service() {
|
|||||||
var callActionUri = ""
|
var callActionUri = ""
|
||||||
var isMainVisible = false
|
var isMainVisible = false
|
||||||
var isMicMuted = false
|
var isMicMuted = false
|
||||||
var preferAndroidContacts = false
|
|
||||||
|
|
||||||
val uas = ArrayList<UserAgent>()
|
val uas = ArrayList<UserAgent>()
|
||||||
val status = ArrayList<Int>()
|
val status = ArrayList<Int>()
|
||||||
@ -1437,10 +1467,13 @@ class BaresipService: Service() {
|
|||||||
var callHistory = ArrayList<NewCallHistory>()
|
var callHistory = ArrayList<NewCallHistory>()
|
||||||
var messages = ArrayList<Message>()
|
var messages = ArrayList<Message>()
|
||||||
val messageUpdate = MutableLiveData<Long>()
|
val messageUpdate = MutableLiveData<Long>()
|
||||||
|
val contactUpdate = MutableLiveData<Long>()
|
||||||
val registrationUpdate = MutableLiveData<Long>()
|
val registrationUpdate = MutableLiveData<Long>()
|
||||||
|
val baresipContacts = ArrayList<Contact.BaresipContact>()
|
||||||
|
val androidContacts = ArrayList<Contact.AndroidContact>()
|
||||||
val contacts = ArrayList<Contact>()
|
val contacts = ArrayList<Contact>()
|
||||||
val androidContacts = ArrayList<AndroidContact>()
|
val contactNames = ArrayList<String>()
|
||||||
val contactNames = mutableListOf<String>()
|
var contactsMode = "baresip"
|
||||||
val chatTexts: MutableMap<String, String> = mutableMapOf()
|
val chatTexts: MutableMap<String, String> = mutableMapOf()
|
||||||
val activities = mutableListOf<String>()
|
val activities = mutableListOf<String>()
|
||||||
var dnsServers = listOf<InetAddress>()
|
var dnsServers = listOf<InetAddress>()
|
||||||
|
|||||||
@ -62,7 +62,7 @@ class CallListAdapter(private val ctx: Context, private val aor: String, private
|
|||||||
if (count <= 3)
|
if (count <= 3)
|
||||||
viewHolder.etcView.text = ""
|
viewHolder.etcView.text = ""
|
||||||
|
|
||||||
val contactName = Utils.contactName(callRow.peerUri)
|
val contactName = Contact.contactName(callRow.peerUri)
|
||||||
if (contactName.startsWith("sip:"))
|
if (contactName.startsWith("sip:"))
|
||||||
viewHolder.peerURIView.text = Utils.friendlyUri(contactName, Utils.aorDomain(callRow.aor))
|
viewHolder.peerURIView.text = Utils.friendlyUri(contactName, Utils.aorDomain(callRow.aor))
|
||||||
else
|
else
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class CallsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
|
listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
|
||||||
val peerUri = uaHistory[pos].peerUri
|
val peerUri = uaHistory[pos].peerUri
|
||||||
var peerName = Utils.contactName(peerUri)
|
var peerName = Contact.contactName(peerUri)
|
||||||
if (peerName.startsWith("sip:"))
|
if (peerName.startsWith("sip:"))
|
||||||
peerName = Utils.friendlyUri(peerName, Utils.aorDomain(aor))
|
peerName = Utils.friendlyUri(peerName, Utils.aorDomain(aor))
|
||||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||||
@ -95,7 +95,7 @@ class CallsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
|
listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
|
||||||
val peerUri = uaHistory[pos].peerUri
|
val peerUri = uaHistory[pos].peerUri
|
||||||
val peerName = Utils.contactName(peerUri)
|
val peerName = Contact.contactName(peerUri)
|
||||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||||
when (which) {
|
when (which) {
|
||||||
DialogInterface.BUTTON_NEGATIVE -> {
|
DialogInterface.BUTTON_NEGATIVE -> {
|
||||||
|
|||||||
@ -63,7 +63,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
this@ChatActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
|
this@ChatActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
|
||||||
|
|
||||||
var chatPeer = Utils.contactName(peerUri)
|
var chatPeer = Contact.contactName(peerUri)
|
||||||
if (chatPeer.startsWith("sip:"))
|
if (chatPeer.startsWith("sip:"))
|
||||||
chatPeer = Utils.friendlyUri(chatPeer, Utils.aorDomain(aor))
|
chatPeer = Utils.friendlyUri(chatPeer, Utils.aorDomain(aor))
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ class ChatActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val builder = AlertDialog.Builder(this@ChatActivity, R.style.Theme_AppCompat)
|
val builder = AlertDialog.Builder(this@ChatActivity, R.style.Theme_AppCompat)
|
||||||
if (Utils.contactName(peerUri) == peerUri)
|
if (Contact.contactName(peerUri) == peerUri)
|
||||||
with (builder) {
|
with (builder) {
|
||||||
setMessage(String.format(getString(R.string.long_message_question),
|
setMessage(String.format(getString(R.string.long_message_question),
|
||||||
chatPeer))
|
chatPeer))
|
||||||
|
|||||||
@ -52,7 +52,7 @@ class ChatListAdapter(private val ctx: Context, private val rows: ArrayList<Mess
|
|||||||
else
|
else
|
||||||
viewHolder.layoutView.setBackgroundResource(R.drawable.message_out_bg)
|
viewHolder.layoutView.setBackgroundResource(R.drawable.message_out_bg)
|
||||||
|
|
||||||
val peerName = Utils.contactName(message.peerUri)
|
val peerName = Contact.contactName(message.peerUri)
|
||||||
viewHolder.peerView.text = if (peerName !=message.peerUri )
|
viewHolder.peerView.text = if (peerName !=message.peerUri )
|
||||||
peerName
|
peerName
|
||||||
else
|
else
|
||||||
|
|||||||
@ -78,14 +78,14 @@ class ChatsActivity: AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
DialogInterface.BUTTON_NEGATIVE -> {
|
DialogInterface.BUTTON_NEGATIVE -> {
|
||||||
val peerUri = uaMessages[pos].peerUri
|
val peerUri = uaMessages[pos].peerUri
|
||||||
val msgs = ArrayList<Message>()
|
val messages = ArrayList<Message>()
|
||||||
for (m in Message.messages())
|
for (m in Message.messages())
|
||||||
if ((m.aor != aor) || (m.peerUri != peerUri))
|
if ((m.aor != aor) || (m.peerUri != peerUri))
|
||||||
msgs.add(m)
|
messages.add(m)
|
||||||
else
|
else
|
||||||
clAdapter.remove(m)
|
clAdapter.remove(m)
|
||||||
clAdapter.notifyDataSetChanged()
|
clAdapter.notifyDataSetChanged()
|
||||||
BaresipService.messages = msgs
|
BaresipService.messages = messages
|
||||||
Message.save()
|
Message.save()
|
||||||
uaMessages = uaMessages(aor)
|
uaMessages = uaMessages(aor)
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ class ChatsActivity: AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val builder = AlertDialog.Builder(this@ChatsActivity, R.style.Theme_AppCompat)
|
val builder = AlertDialog.Builder(this@ChatsActivity, R.style.Theme_AppCompat)
|
||||||
val peer = Utils.contactName(uaMessages[pos].peerUri)
|
val peer = Contact.contactName(uaMessages[pos].peerUri)
|
||||||
if (peer.startsWith("sip:"))
|
if (peer.startsWith("sip:"))
|
||||||
with (builder) {
|
with (builder) {
|
||||||
setMessage(String.format(getString(R.string.long_chat_question),
|
setMessage(String.format(getString(R.string.long_chat_question),
|
||||||
@ -118,12 +118,12 @@ class ChatsActivity: AppCompatActivity() {
|
|||||||
peerUri = binding.peer
|
peerUri = binding.peer
|
||||||
peerUri.threshold = 2
|
peerUri.threshold = 2
|
||||||
peerUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
peerUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||||
Utils.contactNames()))
|
Contact.contactNames()))
|
||||||
|
|
||||||
plusButton.setOnClickListener {
|
plusButton.setOnClickListener {
|
||||||
val uriText = peerUri.text.toString().trim()
|
val uriText = peerUri.text.toString().trim()
|
||||||
if (uriText.isNotEmpty()) {
|
if (uriText.isNotEmpty()) {
|
||||||
var uri = Utils.contactUri(uriText)
|
var uri = Contact.contactUri(uriText)
|
||||||
if (uri == null)
|
if (uri == null)
|
||||||
uri = if (Utils.isTelNumber(uriText))
|
uri = if (Utils.isTelNumber(uriText))
|
||||||
"tel:$uriText"
|
"tel:$uriText"
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.tutpro.baresip
|
package com.tutpro.baresip
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
@ -9,7 +10,7 @@ object Config {
|
|||||||
private val configPath = BaresipService.filesPath + "/config"
|
private val configPath = BaresipService.filesPath + "/config"
|
||||||
private var config = String(Utils.getFileContents(configPath)!!, StandardCharsets.ISO_8859_1)
|
private var config = String(Utils.getFileContents(configPath)!!, StandardCharsets.ISO_8859_1)
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize(ctx: Context) {
|
||||||
|
|
||||||
config = config.replace("module_tmp uuid.so", "module uuid.so")
|
config = config.replace("module_tmp uuid.so", "module uuid.so")
|
||||||
|
|
||||||
@ -85,7 +86,19 @@ object Config {
|
|||||||
config = "${config}jitter_buffer_wish 6\n"
|
config = "${config}jitter_buffer_wish 6\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
BaresipService.preferAndroidContacts = config.contains("prefer_android_contacts yes")
|
removeVariable("prefer_android_contacts")
|
||||||
|
|
||||||
|
if (config.contains("contacts_mode")) {
|
||||||
|
BaresipService.contactsMode = variable("contacts_mode")[0]
|
||||||
|
if (BaresipService.contactsMode != "baresip" &&
|
||||||
|
!Utils.checkPermissions(ctx, arrayOf(Manifest.permission.READ_CONTACTS,
|
||||||
|
Manifest.permission.WRITE_CONTACTS))) {
|
||||||
|
BaresipService.contactsMode = "baresip"
|
||||||
|
replaceVariable("contacts_mode", "baresip")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BaresipService.contactsMode = "baresip"
|
||||||
|
}
|
||||||
|
|
||||||
Utils.putFileContents(configPath, config.toByteArray())
|
Utils.putFileContents(configPath, config.toByteArray())
|
||||||
BaresipService.isConfigInitialized = true
|
BaresipService.isConfigInitialized = true
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityConfigBinding
|
private lateinit var binding: ActivityConfigBinding
|
||||||
private lateinit var layout: ScrollView
|
private lateinit var layout: ScrollView
|
||||||
|
private lateinit var baresipService: Intent
|
||||||
private lateinit var autoStart: CheckBox
|
private lateinit var autoStart: CheckBox
|
||||||
private lateinit var batteryOptimizations: CheckBox
|
private lateinit var batteryOptimizations: CheckBox
|
||||||
private lateinit var listenAddr: EditText
|
private lateinit var listenAddr: EditText
|
||||||
@ -40,11 +41,14 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
private lateinit var verifyServer: CheckBox
|
private lateinit var verifyServer: CheckBox
|
||||||
private lateinit var caFile: CheckBox
|
private lateinit var caFile: CheckBox
|
||||||
private lateinit var darkTheme: CheckBox
|
private lateinit var darkTheme: CheckBox
|
||||||
private lateinit var androidContacts: CheckBox
|
private lateinit var contactsSpinner: Spinner
|
||||||
|
private lateinit var contactsMode: String
|
||||||
|
private lateinit var contactsModes: ArrayList<String>
|
||||||
private lateinit var debug: CheckBox
|
private lateinit var debug: CheckBox
|
||||||
private lateinit var sipTrace: CheckBox
|
private lateinit var sipTrace: CheckBox
|
||||||
private lateinit var reset: CheckBox
|
private lateinit var reset: CheckBox
|
||||||
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
|
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
|
||||||
|
private lateinit var requestPermissionsLauncher: ActivityResultLauncher<Array<String>>
|
||||||
|
|
||||||
private var oldAutoStart = ""
|
private var oldAutoStart = ""
|
||||||
private var oldListenAddr = ""
|
private var oldListenAddr = ""
|
||||||
@ -54,7 +58,7 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
private var oldCAFile = false
|
private var oldCAFile = false
|
||||||
private var oldLogLevel = ""
|
private var oldLogLevel = ""
|
||||||
private var oldDisplayTheme = -1
|
private var oldDisplayTheme = -1
|
||||||
private var oldAndroidContacts = ""
|
private var oldContactsMode = ""
|
||||||
private var save = false
|
private var save = false
|
||||||
private var restart = false
|
private var restart = false
|
||||||
private var menu: Menu? = null
|
private var menu: Menu? = null
|
||||||
@ -63,12 +67,16 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val contactsPermissions = arrayOf(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)
|
||||||
|
|
||||||
binding = ActivityConfigBinding.inflate(layoutInflater)
|
binding = ActivityConfigBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
layout = binding.ConfigView
|
layout = binding.ConfigView
|
||||||
|
|
||||||
Utils.addActivity("config")
|
Utils.addActivity("config")
|
||||||
|
|
||||||
|
baresipService = Intent(this@ConfigActivity, BaresipService::class.java)
|
||||||
|
|
||||||
autoStart = binding.AutoStart
|
autoStart = binding.AutoStart
|
||||||
val asCv = Config.variable("auto_start")
|
val asCv = Config.variable("auto_start")
|
||||||
oldAutoStart = if (asCv.size == 0) "no" else asCv[0]
|
oldAutoStart = if (asCv.size == 0) "no" else asCv[0]
|
||||||
@ -291,10 +299,27 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
oldDisplayTheme = Preferences(applicationContext).displayTheme
|
oldDisplayTheme = Preferences(applicationContext).displayTheme
|
||||||
darkTheme.isChecked = oldDisplayTheme == AppCompatDelegate.MODE_NIGHT_YES
|
darkTheme.isChecked = oldDisplayTheme == AppCompatDelegate.MODE_NIGHT_YES
|
||||||
|
|
||||||
androidContacts = binding.AndroidContacts
|
contactsModes = arrayListOf(
|
||||||
val acCv = Config.variable("prefer_android_contacts")
|
getString(R.string.baresip), getString(R.string.android), getString(R.string.both))
|
||||||
oldAndroidContacts = if (acCv.size == 0) "no" else acCv[0]
|
contactsSpinner = binding.contactsSpinner
|
||||||
androidContacts.isChecked = oldAndroidContacts == "yes"
|
val ctCv = Config.variable("contacts_mode")
|
||||||
|
oldContactsMode = if (ctCv.size == 0) "baresip" else ctCv[0]
|
||||||
|
contactsMode = oldContactsMode
|
||||||
|
contactsModes.removeAt(contactsModes.indexOf(oldContactsMode))
|
||||||
|
contactsModes.add(0, oldContactsMode)
|
||||||
|
val contactsAdapter = ArrayAdapter(this,android.R.layout.simple_spinner_item,
|
||||||
|
contactsModes)
|
||||||
|
contactsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
contactsSpinner.adapter = contactsAdapter
|
||||||
|
contactsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
|
||||||
|
contactsMode = contactsModes[position]
|
||||||
|
if (contactsMode != "baresip" && Build.VERSION.SDK_INT >= 23 &&
|
||||||
|
!Utils.checkPermissions(applicationContext, contactsPermissions))
|
||||||
|
requestPermissions(contactsPermissions, CONTACTS_PERMISSION_REQUEST_CODE)
|
||||||
|
}
|
||||||
|
override fun onNothingSelected(parent: AdapterView<*>) {}
|
||||||
|
}
|
||||||
|
|
||||||
debug = binding.Debug
|
debug = binding.Debug
|
||||||
val dbCv = Config.variable("log_level")
|
val dbCv = Config.variable("log_level")
|
||||||
@ -340,7 +365,14 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
requestPermissionLauncher =
|
requestPermissionLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {}
|
registerForActivityResult(ActivityResultContracts.RequestPermission()) {}
|
||||||
|
requestPermissionsLauncher =
|
||||||
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
|
||||||
|
if (it.containsValue(false)) {
|
||||||
|
contactsMode = oldContactsMode
|
||||||
|
contactsSpinner.setSelection(contactsModes.indexOf(oldContactsMode))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
@ -356,6 +388,44 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
|
||||||
|
grandResults: IntArray) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grandResults)
|
||||||
|
when (requestCode) {
|
||||||
|
CONTACTS_PERMISSION_REQUEST_CODE -> {
|
||||||
|
if (grandResults.contains(PackageManager.PERMISSION_DENIED)) {
|
||||||
|
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 {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
|
||||||
if (BaresipService.activities.indexOf("config") == -1) return true
|
if (BaresipService.activities.indexOf("config") == -1) return true
|
||||||
@ -433,13 +503,28 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
if (oldDisplayTheme != newDisplayTheme)
|
if (oldDisplayTheme != newDisplayTheme)
|
||||||
Preferences(applicationContext).displayTheme = newDisplayTheme
|
Preferences(applicationContext).displayTheme = newDisplayTheme
|
||||||
|
|
||||||
val androidContactsString = if (androidContacts.isChecked)
|
if (oldContactsMode != contactsMode) {
|
||||||
"yes"
|
Config.replaceVariable("contacts_mode", contactsMode)
|
||||||
else
|
BaresipService.contactsMode = contactsMode
|
||||||
"no"
|
when (contactsMode) {
|
||||||
if (oldAndroidContacts != androidContactsString) {
|
"baresip" -> {
|
||||||
Config.replaceVariable("prefer_android_contacts", androidContactsString)
|
BaresipService.androidContacts.clear()
|
||||||
BaresipService.preferAndroidContacts = androidContacts.isChecked
|
Contact.restoreBaresipContacts()
|
||||||
|
baresipService.action = "Stop Content Observer"
|
||||||
|
}
|
||||||
|
"Android" -> {
|
||||||
|
BaresipService.baresipContacts.clear()
|
||||||
|
Contact.loadAndroidContacts(this)
|
||||||
|
baresipService.action = "Start Content Observer"
|
||||||
|
}
|
||||||
|
"Both" -> {
|
||||||
|
Contact.restoreBaresipContacts()
|
||||||
|
Contact.loadAndroidContacts(this)
|
||||||
|
baresipService.action = "Start Content Observer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Contact.contactsUpdate()
|
||||||
|
startService(baresipService)
|
||||||
save = true
|
save = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,9 +615,9 @@ class ConfigActivity : AppCompatActivity() {
|
|||||||
Utils.alertView(this, getString(R.string.dark_theme),
|
Utils.alertView(this, getString(R.string.dark_theme),
|
||||||
getString(R.string.dark_theme_help))
|
getString(R.string.dark_theme_help))
|
||||||
}
|
}
|
||||||
binding.AndroidContactsTitle.setOnClickListener {
|
binding.ContactsTitle.setOnClickListener {
|
||||||
Utils.alertView(this, getString(R.string.show_android_contacts),
|
Utils.alertView(this, getString(R.string.contacts),
|
||||||
getString(R.string.show_android_contacts_help))
|
getString(R.string.contacts_help))
|
||||||
}
|
}
|
||||||
binding.DebugTitle.setOnClickListener {
|
binding.DebugTitle.setOnClickListener {
|
||||||
Utils.alertView(this, getString(R.string.debug), getString(R.string.debug_help))
|
Utils.alertView(this, getString(R.string.debug), getString(R.string.debug_help))
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const val DEFAULT_CHANNEL_ID = "com.tutpro.baresip.default"
|
|||||||
const val HIGH_CHANNEL_ID = "com.tutpro.baresip.high"
|
const val HIGH_CHANNEL_ID = "com.tutpro.baresip.high"
|
||||||
|
|
||||||
const val MIC_PERMISSION_REQUEST_CODE = 1
|
const val MIC_PERMISSION_REQUEST_CODE = 1
|
||||||
const val CONTACT_PERMISSION_REQUEST_CODE = 2
|
const val CONTACTS_PERMISSION_REQUEST_CODE = 2
|
||||||
|
|
||||||
const val STATUS_NOTIFICATION_ID = 101
|
const val STATUS_NOTIFICATION_ID = 101
|
||||||
const val CALL_NOTIFICATION_ID = 102
|
const val CALL_NOTIFICATION_ID = 102
|
||||||
|
|||||||
@ -1,39 +1,165 @@
|
|||||||
package com.tutpro.baresip
|
package com.tutpro.baresip
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.ContactsContract
|
||||||
|
import androidx.core.net.toUri
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
class Contact(var name: String, var uri: String, var color: Int, val id: Long) {
|
sealed class Contact {
|
||||||
|
|
||||||
var avatarImage: Bitmap? = null
|
class BaresipContact(var name: String, var uri: String, var color: Int, val id: Long): Contact() {
|
||||||
var androidContact = false
|
var avatarImage: Bitmap? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
class AndroidContact(var name: String, var color: Int, var thumbnailUri: Uri?): Contact() {
|
||||||
|
val uris = ArrayList<String>()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val CONTACTS_SIZE = 100
|
const val CONTACTS_SIZE = 256
|
||||||
|
|
||||||
fun contacts(): ArrayList<Contact> {
|
fun contacts(): ArrayList<Contact> {
|
||||||
return BaresipService.contacts
|
return BaresipService.contacts
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(): Boolean {
|
fun contactNames(): ArrayList<String> {
|
||||||
|
return BaresipService.contactNames
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
val contact = if (Utils.isTelNumber(userPart))
|
||||||
|
findContact("tel:$userPart")
|
||||||
|
else
|
||||||
|
findContact(uri)
|
||||||
|
if (contact != null) {
|
||||||
|
return when (contact) {
|
||||||
|
is BaresipContact ->
|
||||||
|
contact.name
|
||||||
|
is AndroidContact ->
|
||||||
|
contact.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uri
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return uri of contact name or null if contact is not found
|
||||||
|
fun contactUri(name: String): String? {
|
||||||
|
for (c in contacts())
|
||||||
|
when (c) {
|
||||||
|
is BaresipContact -> {
|
||||||
|
if (c.name.equals(name, ignoreCase = true))
|
||||||
|
return c.uri.removePrefix("<")
|
||||||
|
.replaceAfter(">", "")
|
||||||
|
.replace(">", "")
|
||||||
|
}
|
||||||
|
is AndroidContact -> {
|
||||||
|
if (c.name == name) {
|
||||||
|
if (c.uris.isNotEmpty()) {
|
||||||
|
for (u in c.uris)
|
||||||
|
if (u.startsWith("sip:"))
|
||||||
|
return u
|
||||||
|
return c.uris.first()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findContact(uri: String): Contact? {
|
||||||
|
for (c in contacts())
|
||||||
|
when (c) {
|
||||||
|
is BaresipContact -> {
|
||||||
|
if (Utils.uriMatch(c.uri, uri))
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
is AndroidContact -> {
|
||||||
|
for (u in c.uris)
|
||||||
|
if (Utils.uriMatch(u, uri))
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun nameExists(name: String, ignoreCase: Boolean): Boolean {
|
||||||
|
for (c in BaresipService.baresipContacts)
|
||||||
|
if (c.name.equals(name, ignoreCase = ignoreCase))
|
||||||
|
return true
|
||||||
|
for (c in BaresipService.androidContacts)
|
||||||
|
if (c.name.equals(name, ignoreCase = ignoreCase))
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveBaresipContacts() {
|
||||||
var contents = ""
|
var contents = ""
|
||||||
for (c in BaresipService.contacts) contents +=
|
for (c in BaresipService.contacts)
|
||||||
"\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color};android=${c.androidContact}\n"
|
if (c is BaresipContact)
|
||||||
return Utils.putFileContents(BaresipService.filesPath + "/contacts",
|
contents += "\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color}\n"
|
||||||
|
Utils.putFileContents(BaresipService.filesPath + "/contacts",
|
||||||
contents.toByteArray())
|
contents.toByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restore(): Boolean {
|
fun loadAndroidContacts(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)
|
||||||
|
BaresipService.androidContacts.clear()
|
||||||
|
val contacts = HashMap<Long, AndroidContact>()
|
||||||
|
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()
|
||||||
|
if (nameExists(name, true)) {
|
||||||
|
Log.d(TAG, "Skipping Android contact with existing name '$name'")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val contact = if (contacts.containsKey(id))
|
||||||
|
contacts[id]!!
|
||||||
|
else
|
||||||
|
AndroidContact(name, Utils.randomColor(), 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()
|
||||||
|
for ((_, value) in contacts)
|
||||||
|
if (value.name != "")
|
||||||
|
BaresipService.androidContacts.add(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restoreBaresipContacts(): Boolean {
|
||||||
val content = Utils.getFileContents(BaresipService.filesPath + "/contacts")
|
val content = Utils.getFileContents(BaresipService.filesPath + "/contacts")
|
||||||
?: return false
|
?: return false
|
||||||
val contacts = String(content)
|
val contacts = String(content)
|
||||||
BaresipService.contacts.clear()
|
|
||||||
var contactNo = 0
|
var contactNo = 0
|
||||||
val baseId = System.currentTimeMillis()
|
val baseId = System.currentTimeMillis()
|
||||||
|
BaresipService.baresipContacts.clear()
|
||||||
contacts.lines().forEach {
|
contacts.lines().forEach {
|
||||||
val parts = it.split("\"")
|
val parts = it.split("\"")
|
||||||
if (parts.size == 3) {
|
if (parts.size == 3) {
|
||||||
@ -47,15 +173,13 @@ class Contact(var name: String, var uri: String, var color: Int, val id: Long) {
|
|||||||
colorValue.toInt()
|
colorValue.toInt()
|
||||||
else
|
else
|
||||||
Utils.randomColor()
|
Utils.randomColor()
|
||||||
val androidContact = Utils.paramValue(params, "android" ) == "true"
|
|
||||||
val idValue = Utils.paramValue(params, "id" )
|
val idValue = Utils.paramValue(params, "id" )
|
||||||
val id: Long = if (idValue != "")
|
val id: Long = if (idValue != "")
|
||||||
idValue.toLong()
|
idValue.toLong()
|
||||||
else
|
else
|
||||||
baseId + contactNo
|
baseId + contactNo
|
||||||
Log.d(TAG, "Restoring contact $name, $uri, $color, $id, $androidContact")
|
Log.d(TAG, "Restoring contact $name, $uri, $color, $id")
|
||||||
val contact = Contact(name, uri, color, id)
|
val contact = BaresipContact(name, uri, color, id)
|
||||||
contact.androidContact = androidContact
|
|
||||||
val avatarFilePath = BaresipService.filesPath + "/$id.png"
|
val avatarFilePath = BaresipService.filesPath + "/$id.png"
|
||||||
if (File(avatarFilePath).exists()) {
|
if (File(avatarFilePath).exists()) {
|
||||||
try {
|
try {
|
||||||
@ -67,12 +191,38 @@ class Contact(var name: String, var uri: String, var color: Int, val id: Long) {
|
|||||||
Log.e(TAG, "Could not read avatar image from '$id.img")
|
Log.e(TAG, "Could not read avatar image from '$id.img")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BaresipService.contacts.add(contact)
|
BaresipService.baresipContacts.add(contact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Utils.reloadContactNames()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun contactsUpdate() {
|
||||||
|
BaresipService.contacts.clear()
|
||||||
|
if (BaresipService.contactsMode != "Android")
|
||||||
|
BaresipService.contacts.addAll(BaresipService.baresipContacts)
|
||||||
|
if (BaresipService.contactsMode != "baresip")
|
||||||
|
BaresipService.contacts.addAll(BaresipService.androidContacts)
|
||||||
|
sortContacts()
|
||||||
|
generateContactNames()
|
||||||
|
BaresipService.contactUpdate.postValue(System.nanoTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sortContacts() {
|
||||||
|
BaresipService.contacts.sortBy{ when (it) {
|
||||||
|
is BaresipContact -> it.name
|
||||||
|
is AndroidContact -> it.name
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateContactNames () {
|
||||||
|
BaresipService.contactNames.clear()
|
||||||
|
BaresipService.contactNames.addAll(
|
||||||
|
BaresipService.contacts.map {
|
||||||
|
when (it) {
|
||||||
|
is BaresipContact -> it.name
|
||||||
|
is AndroidContact -> it.name
|
||||||
|
}})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,15 @@
|
|||||||
package com.tutpro.baresip
|
package com.tutpro.baresip
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ContentProviderOperation
|
import android.content.ContentProviderOperation
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.ContactsContract
|
import android.provider.ContactsContract
|
||||||
import android.provider.ContactsContract.CommonDataKinds
|
import android.provider.ContactsContract.CommonDataKinds
|
||||||
@ -21,14 +18,10 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.app.ActivityCompat
|
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import com.tutpro.baresip.Utils.showSnackBar
|
|
||||||
import com.tutpro.baresip.databinding.ActivityContactBinding
|
import com.tutpro.baresip.databinding.ActivityContactBinding
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -44,7 +37,6 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
private lateinit var uriView: EditText
|
private lateinit var uriView: EditText
|
||||||
private lateinit var androidCheck: CheckBox
|
private lateinit var androidCheck: CheckBox
|
||||||
private lateinit var menu: Menu
|
private lateinit var menu: Menu
|
||||||
private lateinit var requestPermissionsLauncher: ActivityResultLauncher<Array<String>>
|
|
||||||
|
|
||||||
private var newContact = false
|
private var newContact = false
|
||||||
private var newAvatar = ""
|
private var newAvatar = ""
|
||||||
@ -53,10 +45,6 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
private var index = 0
|
private var index = 0
|
||||||
private var color = 0
|
private var color = 0
|
||||||
private var id: Long = 0
|
private var id: Long = 0
|
||||||
private var oldAndroid = false
|
|
||||||
|
|
||||||
private val permissions =
|
|
||||||
arrayOf(Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
@ -75,6 +63,10 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
newContact = intent.getBooleanExtra("new", false)
|
newContact = intent.getBooleanExtra("new", false)
|
||||||
|
|
||||||
if (newContact) {
|
if (newContact) {
|
||||||
|
if (BaresipService.contactsMode == "baresip") {
|
||||||
|
binding.AndroidTitle.visibility = View.GONE
|
||||||
|
androidCheck.visibility = View.GONE
|
||||||
|
}
|
||||||
title = getString(R.string.new_contact)
|
title = getString(R.string.new_contact)
|
||||||
color = Utils.randomColor()
|
color = Utils.randomColor()
|
||||||
id = System.currentTimeMillis()
|
id = System.currentTimeMillis()
|
||||||
@ -88,27 +80,33 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
else
|
else
|
||||||
uriView.setText(uri)
|
uriView.setText(uri)
|
||||||
uOrI = uri
|
uOrI = uri
|
||||||
androidCheck.isChecked = false
|
if ((BaresipService.contactsMode == "Android")) {
|
||||||
|
androidCheck.isChecked = true
|
||||||
|
androidCheck.isClickable = false
|
||||||
|
} else {
|
||||||
|
androidCheck.isChecked = false
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
binding.AndroidTitle.visibility = View.GONE
|
||||||
|
androidCheck.visibility = View.GONE
|
||||||
index = intent.getIntExtra("index", 0)
|
index = intent.getIntExtra("index", 0)
|
||||||
val contact = Contact.contacts()[index]
|
val contact = Contact.contacts()[index]
|
||||||
val name = contact.name
|
if (contact is Contact.BaresipContact) {
|
||||||
color = contact.color
|
val name = contact.name
|
||||||
id = contact.id
|
color = contact.color
|
||||||
val avatarImage = contact.avatarImage
|
id = contact.id
|
||||||
if (avatarImage != null)
|
val avatarImage = contact.avatarImage
|
||||||
showImageAvatar(avatarImage)
|
if (avatarImage != null)
|
||||||
else
|
showImageAvatar(avatarImage)
|
||||||
showTextAvatar(name, color)
|
else
|
||||||
title = name
|
showTextAvatar(name, color)
|
||||||
nameView.setText(name)
|
title = name
|
||||||
uriView.setText(contact.uri)
|
nameView.setText(name)
|
||||||
uOrI = index.toString()
|
uriView.setText(contact.uri)
|
||||||
androidCheck.isChecked = contact.androidContact
|
uOrI = index.toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldAndroid = androidCheck.isChecked
|
|
||||||
|
|
||||||
val avatarRequest =
|
val avatarRequest =
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
if (it.resultCode == Activity.RESULT_OK) {
|
if (it.resultCode == Activity.RESULT_OK) {
|
||||||
@ -175,12 +173,6 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
getString(R.string.android_contact_help))
|
getString(R.string.android_contact_help))
|
||||||
}
|
}
|
||||||
|
|
||||||
androidCheck.setOnClickListener{
|
|
||||||
if (Build.VERSION.SDK_INT >= 23)
|
|
||||||
if (!Utils.checkPermissions(this, permissions))
|
|
||||||
requestPermissions(permissions, CONTACT_PERMISSION_REQUEST_CODE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log.d(TAG, "Android sip contacts ${logAndroidContacts(this, "sip")}")
|
// Log.d(TAG, "Android sip contacts ${logAndroidContacts(this, "sip")}")
|
||||||
// Log.d(TAG, "Android tel contacts ${logAndroidContacts(this, "tel")}")
|
// Log.d(TAG, "Android tel contacts ${logAndroidContacts(this, "tel")}")
|
||||||
|
|
||||||
@ -188,12 +180,6 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
requestPermissionsLauncher =
|
|
||||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(optionsMenu: Menu): Boolean {
|
override fun onCreateOptionsMenu(optionsMenu: Menu): Boolean {
|
||||||
|
|
||||||
super.onCreateOptionsMenu(optionsMenu)
|
super.onCreateOptionsMenu(optionsMenu)
|
||||||
@ -205,48 +191,6 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
|
|
||||||
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) {
|
|
||||||
androidCheck.isChecked = oldAndroid
|
|
||||||
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 {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
|
||||||
if (BaresipService.activities.indexOf("contact,$newContact,$uOrI") == -1) return true
|
if (BaresipService.activities.indexOf("contact,$newContact,$uOrI") == -1) return true
|
||||||
@ -265,11 +209,13 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
String.format(getString(R.string.invalid_contact), newName))
|
String.format(getString(R.string.invalid_contact), newName))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val alert: Boolean = if (newContact)
|
val alert: Boolean = if (newContact)
|
||||||
ContactsActivity.nameExists(newName, true)
|
Contact.nameExists(newName, true)
|
||||||
else
|
else {
|
||||||
(Contact.contacts()[index].name != newName) &&
|
val c = Contact.contacts()[index] as Contact.BaresipContact
|
||||||
ContactsActivity.nameExists(newName, false)
|
(c.name != newName) && Contact.nameExists(newName, false)
|
||||||
|
}
|
||||||
if (alert) {
|
if (alert) {
|
||||||
Utils.alertView(this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
String.format(getString(R.string.contact_already_exists), newName))
|
String.format(getString(R.string.contact_already_exists), newName))
|
||||||
@ -287,7 +233,8 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val contact: Contact
|
val contact: Contact.BaresipContact
|
||||||
|
|
||||||
if (newContact) {
|
if (newContact) {
|
||||||
if (Contact.contacts().size >= Contact.CONTACTS_SIZE) {
|
if (Contact.contacts().size >= Contact.CONTACTS_SIZE) {
|
||||||
Utils.alertView(this, getString(R.string.notice),
|
Utils.alertView(this, getString(R.string.notice),
|
||||||
@ -296,16 +243,13 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
BaresipService.activities.removeAt(0)
|
BaresipService.activities.removeAt(0)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
contact = Contact(newName, newUri, color, id)
|
contact = Contact.BaresipContact(newName, newUri, color, id)
|
||||||
contact.androidContact = androidCheck.isChecked
|
|
||||||
Contact.contacts().add(contact)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
contact = Contact.contacts()[index]
|
contact = Contact.contacts()[index] as Contact.BaresipContact
|
||||||
contact.uri = newUri
|
contact.uri = newUri
|
||||||
contact.name = newName
|
contact.name = newName
|
||||||
contact.color = color
|
contact.color = color
|
||||||
contact.androidContact = androidCheck.isChecked
|
|
||||||
}
|
}
|
||||||
|
|
||||||
when (newAvatar) {
|
when (newAvatar) {
|
||||||
@ -323,21 +267,18 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Contact.contacts().sortBy { Contact -> Contact.name }
|
if (androidCheck.isChecked) {
|
||||||
|
addOrUpdateAndroidContact(this, contact)
|
||||||
if (Utils.checkPermissions(this, permissions)) {
|
|
||||||
if (contact.androidContact)
|
|
||||||
addOrUpdateAndroidContact(this, contact)
|
|
||||||
else if (oldAndroid)
|
|
||||||
deleteAndroidContact(this, contact)
|
|
||||||
} else {
|
} else {
|
||||||
contact.androidContact = oldAndroid
|
if (newContact)
|
||||||
|
Contact.contacts().add(contact)
|
||||||
|
Contact.sortContacts()
|
||||||
|
Contact.generateContactNames()
|
||||||
|
Contact.saveBaresipContacts()
|
||||||
}
|
}
|
||||||
|
|
||||||
Contact.save()
|
|
||||||
Utils.reloadContactNames()
|
|
||||||
|
|
||||||
BaresipService.activities.remove("contact,$newContact,$uOrI")
|
BaresipService.activities.remove("contact,$newContact,$uOrI")
|
||||||
|
|
||||||
val i = Intent(this, MainActivity::class.java)
|
val i = Intent(this, MainActivity::class.java)
|
||||||
i.putExtra("name", newName)
|
i.putExtra("name", newName)
|
||||||
setResult(Activity.RESULT_OK, i)
|
setResult(Activity.RESULT_OK, i)
|
||||||
@ -407,7 +348,7 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
return rotatedBitmap
|
return rotatedBitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addOrUpdateAndroidContact(ctx: Context, contact: Contact) {
|
private fun addOrUpdateAndroidContact(ctx: Context, contact: Contact.BaresipContact) {
|
||||||
val projection = arrayOf(ContactsContract.Data.RAW_CONTACT_ID)
|
val projection = arrayOf(ContactsContract.Data.RAW_CONTACT_ID)
|
||||||
val selection = ContactsContract.Data.MIMETYPE + "='" +
|
val selection = ContactsContract.Data.MIMETYPE + "='" +
|
||||||
CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "' AND " +
|
CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "' AND " +
|
||||||
@ -420,10 +361,9 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
addAndroidContact(ctx, contact)
|
addAndroidContact(ctx, contact)
|
||||||
}
|
}
|
||||||
c?.close()
|
c?.close()
|
||||||
contact.androidContact = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addAndroidContact(ctx: Context, contact: Contact): Boolean {
|
private fun addAndroidContact(ctx: Context, contact: Contact.BaresipContact): Boolean {
|
||||||
val ops = ArrayList<ContentProviderOperation>()
|
val ops = ArrayList<ContentProviderOperation>()
|
||||||
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
|
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
|
||||||
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
|
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
|
||||||
@ -464,7 +404,7 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAndroidContact(rawContactId: Long, contact: Contact) {
|
private fun updateAndroidContact(rawContactId: Long, contact: Contact.BaresipContact) {
|
||||||
if (updateAndroidUri(rawContactId, contact.uri) == 0)
|
if (updateAndroidUri(rawContactId, contact.uri) == 0)
|
||||||
addAndroidUri(rawContactId, contact.uri)
|
addAndroidUri(rawContactId, contact.uri)
|
||||||
if (updateAndroidPhoto(rawContactId, contact.avatarImage) == 0)
|
if (updateAndroidPhoto(rawContactId, contact.avatarImage) == 0)
|
||||||
@ -561,9 +501,9 @@ class ContactActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
var contact: Contact? = null
|
var contact: Contact? = null
|
||||||
|
|
||||||
fun deleteAndroidContact(ctx: Context, contact: Contact): Int {
|
fun deleteAndroidContact(ctx: Context, name: String): Int {
|
||||||
return ctx.contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI,
|
return ctx.contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI,
|
||||||
ContactsContract.Contacts.DISPLAY_NAME + "='" + contact.name + "'",
|
ContactsContract.Contacts.DISPLAY_NAME + "='" + name + "'",
|
||||||
null)
|
null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
package com.tutpro.baresip
|
package com.tutpro.baresip
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.*
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.content.ContextCompat.startActivity
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<Contact>,
|
class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<Contact>,
|
||||||
private val aor: String) :
|
private val aor: String) :
|
||||||
@ -48,82 +48,137 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
|
|||||||
|
|
||||||
val contact = rows[position]
|
val contact = rows[position]
|
||||||
|
|
||||||
val avatarImage = contact.avatarImage
|
if (contact is Contact.BaresipContact) {
|
||||||
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))
|
|
||||||
}
|
|
||||||
|
|
||||||
viewHolder.nameView.text = contact.name
|
val avatarImage = contact.avatarImage
|
||||||
viewHolder.nameView.textSize = 20f
|
if (avatarImage != null) {
|
||||||
viewHolder.nameView.setPadding(6, 6, 0, 6)
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
if (aor != "") {
|
viewHolder.nameView.text = contact.name
|
||||||
viewHolder.nameView.setOnClickListener {
|
viewHolder.nameView.textSize = 20f
|
||||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
viewHolder.nameView.setPadding(6, 6, 0, 6)
|
||||||
when (which) {
|
|
||||||
DialogInterface.BUTTON_POSITIVE, DialogInterface.BUTTON_NEGATIVE -> {
|
if (aor != "") {
|
||||||
val i = Intent(ctx, MainActivity::class.java)
|
viewHolder.nameView.setOnClickListener {
|
||||||
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or
|
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||||
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
when (which) {
|
||||||
if (which == DialogInterface.BUTTON_NEGATIVE)
|
DialogInterface.BUTTON_POSITIVE, DialogInterface.BUTTON_NEGATIVE -> {
|
||||||
i.putExtra("action", "call")
|
val i = Intent(ctx, MainActivity::class.java)
|
||||||
else
|
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||||
i.putExtra("action", "message")
|
Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
val ua = UserAgent.ofAor(aor)
|
if (which == DialogInterface.BUTTON_NEGATIVE)
|
||||||
if (ua == null) {
|
i.putExtra("action", "call")
|
||||||
Log.w(TAG, "onClickListener did not find AoR $aor")
|
else
|
||||||
} else {
|
i.putExtra("action", "message")
|
||||||
BaresipService.activities.clear()
|
val ua = UserAgent.ofAor(aor)
|
||||||
i.putExtra("uap", ua.uap)
|
if (ua == null) {
|
||||||
i.putExtra("peer", contact.uri)
|
Log.w(TAG, "onClickListener did not find AoR $aor")
|
||||||
(ctx as Activity).startActivity(i)
|
} else {
|
||||||
|
BaresipService.activities.clear()
|
||||||
|
i.putExtra("uap", ua.uap)
|
||||||
|
i.putExtra("peer", contact.uri)
|
||||||
|
(ctx as Activity).startActivity(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DialogInterface.BUTTON_NEUTRAL -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DialogInterface.BUTTON_NEUTRAL -> {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
||||||
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
lastClick = SystemClock.elapsedRealtime()
|
||||||
lastClick = SystemClock.elapsedRealtime()
|
with(AlertDialog.Builder(ctx, R.style.Theme_AppCompat)) {
|
||||||
with (AlertDialog.Builder(ctx, R.style.Theme_AppCompat)) {
|
setMessage(String.format(ctx.getString(R.string.contact_action_question),
|
||||||
setMessage(String.format(ctx.getString(R.string.contact_action_question),
|
contact.name))
|
||||||
Contact.contacts()[position].name))
|
setNeutralButton(ctx.getText(R.string.cancel), dialogClickListener)
|
||||||
setNeutralButton(ctx.getText(R.string.cancel), dialogClickListener)
|
setNegativeButton(ctx.getText(R.string.call), dialogClickListener)
|
||||||
setNegativeButton(ctx.getText(R.string.call), dialogClickListener)
|
setPositiveButton(ctx.getText(R.string.send_message), dialogClickListener)
|
||||||
setPositiveButton(ctx.getText(R.string.send_message), dialogClickListener)
|
show()
|
||||||
show()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewHolder.actionView.visibility = View.VISIBLE
|
||||||
|
viewHolder.actionView.setOnClickListener {
|
||||||
|
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
||||||
|
lastClick = SystemClock.elapsedRealtime()
|
||||||
|
val i = Intent(ctx, ContactActivity::class.java)
|
||||||
|
val b = Bundle()
|
||||||
|
b.putBoolean("new", false)
|
||||||
|
b.putInt("index", position)
|
||||||
|
i.putExtras(b)
|
||||||
|
startActivity(ctx, i, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contact is Contact.AndroidContact) {
|
||||||
|
|
||||||
|
val thumbNailUri = contact.thumbnailUri
|
||||||
|
if (thumbNailUri != null) {
|
||||||
|
viewHolder.imageAvatarView.setImageURI(thumbNailUri)
|
||||||
|
} 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
viewHolder.nameView.text = contact.name
|
||||||
|
viewHolder.nameView.textSize = 20f
|
||||||
|
viewHolder.nameView.setPadding(6, 6, 0, 6)
|
||||||
|
|
||||||
|
viewHolder.nameView.setOnClickListener {
|
||||||
|
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
||||||
|
lastClick = SystemClock.elapsedRealtime()
|
||||||
|
val i = Intent(ctx, AndroidContactActivity::class.java)
|
||||||
|
val b = Bundle()
|
||||||
|
b.putString("aor", aor)
|
||||||
|
b.putInt("index", position)
|
||||||
|
i.putExtras(b)
|
||||||
|
startActivity(ctx, i, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewHolder.actionView.visibility = View.GONE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewHolder.nameView.setOnLongClickListener {
|
viewHolder.nameView.setOnLongClickListener {
|
||||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||||
when (which) {
|
when (which) {
|
||||||
DialogInterface.BUTTON_POSITIVE -> {
|
DialogInterface.BUTTON_POSITIVE -> {
|
||||||
val id = contact.id
|
when (contact) {
|
||||||
val avatarFile = File(BaresipService.filesPath, "$id.img")
|
is Contact.BaresipContact -> {
|
||||||
if (avatarFile.exists()) {
|
val id = contact.id
|
||||||
try {
|
val avatarFile = File(BaresipService.filesPath, "$id.img")
|
||||||
avatarFile.delete()
|
if (avatarFile.exists()) {
|
||||||
} catch (e: IOException) {
|
try {
|
||||||
Log.e(TAG, "Could not delete file '$id.img")
|
avatarFile.delete()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e(TAG, "Could not delete file '$id.img")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Contact.contacts().removeAt(position)
|
||||||
|
Contact.contactNames().removeAt(position)
|
||||||
|
Contact.saveBaresipContacts()
|
||||||
|
this.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
is Contact.AndroidContact -> {
|
||||||
|
ContactActivity.deleteAndroidContact(ctx, contact.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (contact.androidContact &&
|
|
||||||
Utils.checkPermissions(ctx, arrayOf(Manifest.permission.WRITE_CONTACTS)))
|
|
||||||
ContactActivity.deleteAndroidContact(ctx, contact)
|
|
||||||
Contact.contacts().removeAt(position)
|
|
||||||
Contact.save()
|
|
||||||
Utils.reloadContactNames()
|
|
||||||
this.notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
DialogInterface.BUTTON_NEGATIVE -> {
|
DialogInterface.BUTTON_NEGATIVE -> {
|
||||||
}
|
}
|
||||||
@ -131,10 +186,13 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
|
|||||||
}
|
}
|
||||||
val titleView = View.inflate(ctx, R.layout.alert_title, null) as TextView
|
val titleView = View.inflate(ctx, R.layout.alert_title, null) as TextView
|
||||||
titleView.text = ctx.getString(R.string.confirmation)
|
titleView.text = ctx.getString(R.string.confirmation)
|
||||||
with (AlertDialog.Builder(ctx)) {
|
with(AlertDialog.Builder(ctx)) {
|
||||||
setCustomTitle(titleView)
|
setCustomTitle(titleView)
|
||||||
setMessage(String.format(ctx.getString(R.string.contact_delete_question),
|
setMessage(String.format(ctx.getString(R.string.contact_delete_question),
|
||||||
Contact.contacts()[position].name))
|
when (contact) {
|
||||||
|
is Contact.BaresipContact -> contact.name
|
||||||
|
is Contact.AndroidContact -> contact.name
|
||||||
|
}))
|
||||||
setNegativeButton(ctx.getText(R.string.cancel), dialogClickListener)
|
setNegativeButton(ctx.getText(R.string.cancel), dialogClickListener)
|
||||||
setPositiveButton(ctx.getText(R.string.delete), dialogClickListener)
|
setPositiveButton(ctx.getText(R.string.delete), dialogClickListener)
|
||||||
show()
|
show()
|
||||||
@ -142,18 +200,6 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
viewHolder.actionView.setOnClickListener {
|
|
||||||
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
|
||||||
lastClick = SystemClock.elapsedRealtime()
|
|
||||||
val i = Intent(ctx, ContactActivity::class.java)
|
|
||||||
val b = Bundle()
|
|
||||||
b.putBoolean("new", false)
|
|
||||||
b.putInt("index", position)
|
|
||||||
i.putExtras(b)
|
|
||||||
startActivity(ctx, i, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowView
|
return rowView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import android.app.Activity
|
|||||||
import android.content.*
|
import android.content.*
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.view.Menu
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import com.tutpro.baresip.databinding.ActivityContactsBinding
|
import com.tutpro.baresip.databinding.ActivityContactsBinding
|
||||||
|
|
||||||
class ContactsActivity : AppCompatActivity() {
|
class ContactsActivity : AppCompatActivity() {
|
||||||
@ -27,10 +27,15 @@ class ContactsActivity : AppCompatActivity() {
|
|||||||
Utils.addActivity("contacts,$aor")
|
Utils.addActivity("contacts,$aor")
|
||||||
|
|
||||||
val listView = binding.contacts
|
val listView = binding.contacts
|
||||||
clAdapter = ContactListAdapter(this, Contact.contacts(), aor)
|
clAdapter = ContactListAdapter(this, BaresipService.contacts, aor)
|
||||||
listView.adapter = clAdapter
|
listView.adapter = clAdapter
|
||||||
listView.isLongClickable = true
|
listView.isLongClickable = true
|
||||||
|
|
||||||
|
val contactObserver = Observer<Long> {
|
||||||
|
clAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
BaresipService.contactUpdate.observe(this, contactObserver)
|
||||||
|
|
||||||
val contactRequest =
|
val contactRequest =
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
if (it.resultCode == RESULT_OK)
|
if (it.resultCode == RESULT_OK)
|
||||||
@ -58,34 +63,14 @@ class ContactsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.swap_contacts_icon, menu)
|
|
||||||
return super.onCreateOptionsMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
clAdapter.notifyDataSetChanged()
|
clAdapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
|
|
||||||
R.id.swapIcon -> {
|
|
||||||
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
|
||||||
lastClick = SystemClock.elapsedRealtime()
|
|
||||||
BaresipService.activities.remove("contacts,$aor")
|
|
||||||
val intent = Intent(this, AndroidContactsActivity::class.java)
|
|
||||||
intent.putExtra("aor", aor)
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
BaresipService.activities.remove("contacts,$aor")
|
BaresipService.activities.remove("contacts,$aor")
|
||||||
setResult(Activity.RESULT_OK, Intent())
|
setResult(Activity.RESULT_OK, Intent())
|
||||||
@ -105,40 +90,4 @@ class ContactsActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
// Return uri of contact name or null if contact is not found
|
|
||||||
fun contactUri(name: String): String? {
|
|
||||||
for (c in Contact.contacts())
|
|
||||||
if (c.name.equals(name, ignoreCase = true))
|
|
||||||
return c.uri.removePrefix("<")
|
|
||||||
.replaceAfter(">", "")
|
|
||||||
.replace(">", "")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return contact name of uri or null 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
|
|
||||||
else
|
|
||||||
findContact(uri)?.name
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findContact(uri: String): Contact? {
|
|
||||||
for (c in Contact.contacts()) {
|
|
||||||
if (Utils.uriMatch(c.uri, uri))
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun nameExists(name: String, ignoreCase: Boolean): Boolean {
|
|
||||||
for (c in Contact.contacts())
|
|
||||||
if (c.name.equals(name, ignoreCase = ignoreCase)) return true
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -209,11 +209,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
// Haven't found any explanation why this can happen.
|
// Haven't found any explanation why this can happen.
|
||||||
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
||||||
Log.d(TAG, "aorSpinner selecting $position")
|
Log.d(TAG, "aorSpinner selecting $position")
|
||||||
val acc = UserAgent.uas()[position].account
|
if (position < UserAgent.uas().size) {
|
||||||
aorSpinner.tag = acc.aor
|
val acc = UserAgent.uas()[position].account
|
||||||
val ua = UserAgent.uas()[position]
|
aorSpinner.tag = acc.aor
|
||||||
showCall(ua)
|
val ua = UserAgent.uas()[position]
|
||||||
updateIcons(acc)
|
showCall(ua)
|
||||||
|
updateIcons(acc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
override fun onNothingSelected(parent: AdapterView<*>) {
|
override fun onNothingSelected(parent: AdapterView<*>) {
|
||||||
Log.d(TAG, "Nothing selected")
|
Log.d(TAG, "Nothing selected")
|
||||||
@ -273,7 +275,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||||
Utils.contactNames()))
|
Contact.contactNames()))
|
||||||
callUri.threshold = 2
|
callUri.threshold = 2
|
||||||
callUri.setOnFocusChangeListener { view, b ->
|
callUri.setOnFocusChangeListener { view, b ->
|
||||||
if (b) {
|
if (b) {
|
||||||
@ -456,27 +458,18 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
contactsRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
contactsRequest = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||||
Utils.contactNames()))
|
Contact.contactNames()))
|
||||||
}
|
}
|
||||||
|
|
||||||
contactsButton.setOnClickListener {
|
contactsButton.setOnClickListener {
|
||||||
if (BaresipService.preferAndroidContacts) {
|
val i = Intent(this@MainActivity, ContactsActivity::class.java)
|
||||||
val i = Intent(this@MainActivity, AndroidContactsActivity::class.java)
|
val b = Bundle()
|
||||||
if (aorSpinner.selectedItemPosition >= 0)
|
if (aorSpinner.selectedItemPosition >= 0)
|
||||||
i.putExtra("aor", aorSpinner.tag.toString())
|
b.putString("aor", aorSpinner.tag.toString())
|
||||||
else
|
else
|
||||||
i.putExtra("aor", "")
|
b.putString("aor", "")
|
||||||
startActivity(i)
|
i.putExtras(b)
|
||||||
} else {
|
contactsRequest.launch(i)
|
||||||
val i = Intent(this@MainActivity, ContactsActivity::class.java)
|
|
||||||
val b = Bundle()
|
|
||||||
if (aorSpinner.selectedItemPosition >= 0)
|
|
||||||
b.putString("aor", aorSpinner.tag.toString())
|
|
||||||
else
|
|
||||||
b.putString("aor", "")
|
|
||||||
i.putExtras(b)
|
|
||||||
contactsRequest.launch(i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chatRequests = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
chatRequests = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
@ -932,6 +925,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (event == "started") {
|
if (event == "started") {
|
||||||
val callActionUri = params[0]
|
val callActionUri = params[0]
|
||||||
Log.d(TAG, "Handling service event 'started' with '$callActionUri'")
|
Log.d(TAG, "Handling service event 'started' with '$callActionUri'")
|
||||||
|
if (!this::uaAdapter.isInitialized) {
|
||||||
|
// Android has restarted baresip when permission has been denied in app settings
|
||||||
|
val i = Intent(this, MainActivity::class.java)
|
||||||
|
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
startActivity(i)
|
||||||
|
return
|
||||||
|
}
|
||||||
uaAdapter.notifyDataSetChanged()
|
uaAdapter.notifyDataSetChanged()
|
||||||
if (callActionUri != "") {
|
if (callActionUri != "") {
|
||||||
var ua = UserAgent.ofDomain(Utils.uriHostPart(callActionUri))
|
var ua = UserAgent.ofDomain(Utils.uriHostPart(callActionUri))
|
||||||
@ -1105,7 +1105,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val call = Call.ofCallp(callp)!!
|
val call = Call.ofCallp(callp)!!
|
||||||
val titleView = View.inflate(this, R.layout.alert_title, null) as TextView
|
val titleView = View.inflate(this, R.layout.alert_title, null) as TextView
|
||||||
titleView.text = getString(R.string.transfer_request)
|
titleView.text = getString(R.string.transfer_request)
|
||||||
val target = Utils.friendlyUri(Utils.contactName(ev[1]), Utils.aorDomain(aor))
|
val target = Utils.friendlyUri(Contact.contactName(ev[1]), Utils.aorDomain(aor))
|
||||||
with(AlertDialog.Builder(this)) {
|
with(AlertDialog.Builder(this)) {
|
||||||
setCustomTitle(titleView)
|
setCustomTitle(titleView)
|
||||||
setMessage(String.format(getString(R.string.transfer_request_query),
|
setMessage(String.format(getString(R.string.transfer_request_query),
|
||||||
@ -1403,7 +1403,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
titleView.text = getString(R.string.call_transfer)
|
titleView.text = getString(R.string.call_transfer)
|
||||||
val transferUri = layout.findViewById(R.id.transferUri) as AutoCompleteTextView
|
val transferUri = layout.findViewById(R.id.transferUri) as AutoCompleteTextView
|
||||||
transferUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
transferUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||||
Utils.contactNames()))
|
Contact.contactNames()))
|
||||||
transferUri.threshold = 2
|
transferUri.threshold = 2
|
||||||
transferUri.requestFocus()
|
transferUri.requestFocus()
|
||||||
val builder = AlertDialog.Builder(this)
|
val builder = AlertDialog.Builder(this)
|
||||||
@ -1414,7 +1414,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
var uriText = transferUri.text.toString().trim()
|
var uriText = transferUri.text.toString().trim()
|
||||||
if (uriText.isNotEmpty()) {
|
if (uriText.isNotEmpty()) {
|
||||||
uriText = Utils.contactUri(uriText) ?: uriText
|
uriText = Contact.contactUri(uriText) ?: uriText
|
||||||
if (Utils.isTelNumber(uriText))
|
if (Utils.isTelNumber(uriText))
|
||||||
uriText = "tel:$uriText"
|
uriText = "tel:$uriText"
|
||||||
val uri = if (Utils.isTelUri(uriText))
|
val uri = if (Utils.isTelUri(uriText))
|
||||||
@ -1702,7 +1702,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (Call.calls().isEmpty()) {
|
if (Call.calls().isEmpty()) {
|
||||||
var uriText = callUri.text.toString().trim()
|
var uriText = callUri.text.toString().trim()
|
||||||
if (uriText.isNotEmpty()) {
|
if (uriText.isNotEmpty()) {
|
||||||
uriText = Utils.contactUri(uriText) ?: uriText
|
uriText = Contact.contactUri(uriText) ?: uriText
|
||||||
if (Utils.isTelNumber(uriText))
|
if (Utils.isTelNumber(uriText))
|
||||||
uriText = "tel:$uriText"
|
uriText = "tel:$uriText"
|
||||||
val uri = if (Utils.isTelUri(uriText)) {
|
val uri = if (Utils.isTelUri(uriText)) {
|
||||||
@ -1750,10 +1750,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
} else {
|
} else {
|
||||||
val latest = NewCallHistory.aorLatestHistory(aor)
|
val latest = NewCallHistory.aorLatestHistory(aor)
|
||||||
if (latest != null)
|
if (latest != null)
|
||||||
callUri.setText(
|
callUri.setText(Utils.friendlyUri(Contact.contactName(latest.peerUri),
|
||||||
Utils.friendlyUri(Utils.contactName(latest.peerUri), Utils.aorDomain(aor)
|
Utils.aorDomain(aor)))
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1772,7 +1770,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
callUri.isFocusableInTouchMode = true
|
callUri.isFocusableInTouchMode = true
|
||||||
imm.hideSoftInputFromWindow(callUri.windowToken, 0)
|
imm.hideSoftInputFromWindow(callUri.windowToken, 0)
|
||||||
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
callUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item,
|
||||||
Utils.contactNames()))
|
Contact.contactNames()))
|
||||||
securityButton.visibility = View.INVISIBLE
|
securityButton.visibility = View.INVISIBLE
|
||||||
callButton.visibility = View.VISIBLE
|
callButton.visibility = View.VISIBLE
|
||||||
callButton.isEnabled = true
|
callButton.isEnabled = true
|
||||||
@ -1797,7 +1795,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
else
|
else
|
||||||
getString(R.string.outgoing_call_to_dots)
|
getString(R.string.outgoing_call_to_dots)
|
||||||
callTimer.visibility = View.INVISIBLE
|
callTimer.visibility = View.INVISIBLE
|
||||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri),
|
callUri.setText(Utils.friendlyUri(Contact.contactName(call.peerUri),
|
||||||
Utils.aorDomain(ua.account.aor)))
|
Utils.aorDomain(ua.account.aor)))
|
||||||
securityButton.visibility = View.INVISIBLE
|
securityButton.visibility = View.INVISIBLE
|
||||||
callButton.visibility = View.INVISIBLE
|
callButton.visibility = View.INVISIBLE
|
||||||
@ -1812,7 +1810,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
"incoming" -> {
|
"incoming" -> {
|
||||||
callTitle.text = getString(R.string.incoming_call_from_dots)
|
callTitle.text = getString(R.string.incoming_call_from_dots)
|
||||||
callTimer.visibility = View.INVISIBLE
|
callTimer.visibility = View.INVISIBLE
|
||||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri),
|
callUri.setText(Utils.friendlyUri(Contact.contactName(call.peerUri),
|
||||||
Utils.aorDomain(ua.account.aor)))
|
Utils.aorDomain(ua.account.aor)))
|
||||||
callUri.setAdapter(null)
|
callUri.setAdapter(null)
|
||||||
securityButton.visibility = View.INVISIBLE
|
securityButton.visibility = View.INVISIBLE
|
||||||
@ -1832,7 +1830,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
if (call.referTo != "") {
|
if (call.referTo != "") {
|
||||||
callTitle.text = getString(R.string.transferring_call_to_dots)
|
callTitle.text = getString(R.string.transferring_call_to_dots)
|
||||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.referTo),
|
callUri.setText(Utils.friendlyUri(Contact.contactName(call.referTo),
|
||||||
Utils.aorDomain(ua.account.aor)))
|
Utils.aorDomain(ua.account.aor)))
|
||||||
transferButton.isEnabled = false
|
transferButton.isEnabled = false
|
||||||
} else {
|
} else {
|
||||||
@ -1840,7 +1838,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
callTitle.text = getString(R.string.outgoing_call_to_dots)
|
callTitle.text = getString(R.string.outgoing_call_to_dots)
|
||||||
else
|
else
|
||||||
callTitle.text = getString(R.string.incoming_call_from_dots)
|
callTitle.text = getString(R.string.incoming_call_from_dots)
|
||||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri),
|
callUri.setText(Utils.friendlyUri(Contact.contactName(call.peerUri),
|
||||||
Utils.aorDomain(ua.account.aor)))
|
Utils.aorDomain(ua.account.aor)))
|
||||||
transferButton.isEnabled = true
|
transferButton.isEnabled = true
|
||||||
}
|
}
|
||||||
@ -1973,21 +1971,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
i.putExtras(b)
|
i.putExtras(b)
|
||||||
startActivity(i)
|
startActivity(i)
|
||||||
}
|
}
|
||||||
"android contacts" -> {
|
|
||||||
val i = Intent(this, AndroidContactsActivity::class.java)
|
|
||||||
val b = Bundle()
|
|
||||||
b.putString("aor", activity[1])
|
|
||||||
i.putExtras(b)
|
|
||||||
startActivity(i)
|
|
||||||
}
|
|
||||||
"android contact" -> {
|
|
||||||
val i = Intent(this, AndroidContactActivity::class.java)
|
|
||||||
val b = Bundle()
|
|
||||||
b.putString("aor", activity[1])
|
|
||||||
b.putInt("index", activity[2].toInt())
|
|
||||||
i.putExtras(b)
|
|
||||||
startActivity(i)
|
|
||||||
}
|
|
||||||
"chats" -> {
|
"chats" -> {
|
||||||
val i = Intent(this, ChatsActivity::class.java)
|
val i = Intent(this, ChatsActivity::class.java)
|
||||||
val b = Bundle()
|
val b = Bundle()
|
||||||
|
|||||||
@ -45,7 +45,7 @@ class MessageListAdapter(private val ctx: Context, private val rows: ArrayList<M
|
|||||||
val peer: String = if (down) {
|
val peer: String = if (down) {
|
||||||
lp.setMargins(0, 10, 75, 10)
|
lp.setMargins(0, 10, 75, 10)
|
||||||
viewHolder.layoutView.setBackgroundResource(R.drawable.message_in_bg)
|
viewHolder.layoutView.setBackgroundResource(R.drawable.message_in_bg)
|
||||||
val contactName = Utils.contactName(message.peerUri)
|
val contactName = Contact.contactName(message.peerUri)
|
||||||
if (contactName.startsWith("sip:") &&
|
if (contactName.startsWith("sip:") &&
|
||||||
(Utils.uriHostPart(message.peerUri) == Utils.uriHostPart(message.aor)))
|
(Utils.uriHostPart(message.peerUri) == Utils.uriHostPart(message.aor)))
|
||||||
Utils.uriUserPart(message.peerUri)
|
Utils.uriUserPart(message.peerUri)
|
||||||
|
|||||||
@ -320,57 +320,43 @@ object Utils {
|
|||||||
name.lines().size == 1 && !name.contains('"')
|
name.lines().size == 1 && !name.contains('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
fun contactName(uri: String) : String {
|
|
||||||
return ContactsActivity.contactName(uri) ?: AndroidContactsActivity.contactName(uri)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun contactUri(name: String) : String? {
|
|
||||||
return ContactsActivity.contactUri(name) ?: AndroidContactsActivity.contactUri(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reloadContactNames() {
|
|
||||||
BaresipService.contactNames.clear()
|
|
||||||
BaresipService.contactNames.addAll(Contact.contacts().map{Contact -> Contact.name})
|
|
||||||
BaresipService.contactNames.addAll(AndroidContact.contacts().map{AndroidContact -> AndroidContact.name})
|
|
||||||
BaresipService.contactNames.sort()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun contactNames() : List<String> {
|
|
||||||
return BaresipService.contactNames
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAvatar(ctx: Context, imageView: ImageView, textView: TextView, uri: String) {
|
fun setAvatar(ctx: Context, imageView: ImageView, textView: TextView, uri: String) {
|
||||||
val contact = ContactsActivity.findContact(uri)
|
|
||||||
if (contact != null) {
|
when (val contact = Contact.findContact(uri)) {
|
||||||
val avatarImage = contact.avatarImage
|
|
||||||
if (avatarImage != null) {
|
is Contact.BaresipContact -> {
|
||||||
imageView.setImageBitmap(avatarImage)
|
val avatarImage = contact.avatarImage
|
||||||
} else {
|
if (avatarImage != null) {
|
||||||
textView.background.setTint(contact.color)
|
imageView.setImageBitmap(avatarImage)
|
||||||
if (contact.name.isNotEmpty())
|
|
||||||
textView.text = "${contact.name[0]}"
|
|
||||||
else
|
|
||||||
textView.text = ""
|
|
||||||
imageView.setImageBitmap(bitmapFromView(textView))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val androidContact = AndroidContactsActivity.findContact(uri)
|
|
||||||
if (androidContact != null) {
|
|
||||||
val thumbnailUri = androidContact.thumbnailUri
|
|
||||||
if (thumbnailUri != null) {
|
|
||||||
imageView.setImageURI(thumbnailUri)
|
|
||||||
} else {
|
} else {
|
||||||
textView.background.setTint(androidContact.color)
|
textView.background.setTint(contact.color)
|
||||||
if (androidContact.name.isNotEmpty())
|
if (contact.name.isNotEmpty())
|
||||||
textView.text = "${androidContact.name[0]}"
|
textView.text = "${contact.name[0]}"
|
||||||
else
|
else
|
||||||
textView.text = ""
|
textView.text = ""
|
||||||
imageView.setImageBitmap(bitmapFromView(textView))
|
imageView.setImageBitmap(bitmapFromView(textView))
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
is Contact.AndroidContact -> {
|
||||||
|
val thumbnailUri = contact.thumbnailUri
|
||||||
|
if (thumbnailUri != null) {
|
||||||
|
imageView.setImageURI(thumbnailUri)
|
||||||
|
} else {
|
||||||
|
textView.background.setTint(contact.color)
|
||||||
|
if (contact.name.isNotEmpty())
|
||||||
|
textView.text = "${contact.name[0]}"
|
||||||
|
else
|
||||||
|
textView.text = ""
|
||||||
|
imageView.setImageBitmap(bitmapFromView(textView))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
null -> {
|
||||||
val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.person_image)
|
val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.person_image)
|
||||||
imageView.setImageBitmap(bitmap)
|
imageView.setImageBitmap(bitmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -215,37 +215,27 @@
|
|||||||
android:id="@+id/AudioSettingsTitle"
|
android:id="@+id/AudioSettingsTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="@string/audio_settings" >
|
android:text="@string/audio_settings" >
|
||||||
</TextView>
|
</TextView>
|
||||||
|
|
||||||
<RelativeLayout
|
<TextView
|
||||||
|
android:id="@+id/ContactsTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="@string/contacts" >
|
||||||
|
</TextView>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/contactsSpinner"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
android:orientation="horizontal" >
|
android:paddingTop="8dp" >
|
||||||
<TextView
|
</Spinner>
|
||||||
android:id="@+id/AndroidContactsTitle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toStartOf="@id/AndroidContacts"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:text="@string/show_android_contacts" >
|
|
||||||
</TextView>
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/AndroidContacts"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:checked="false" >
|
|
||||||
</CheckBox>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@ -262,6 +262,7 @@
|
|||||||
android:src="@drawable/voicemail"
|
android:src="@drawable/voicemail"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
|
android:visibility="invisible"
|
||||||
android:contentDescription="@string/voicemail" >
|
android:contentDescription="@string/voicemail" >
|
||||||
</ImageButton>
|
</ImageButton>
|
||||||
|
|
||||||
|
|||||||
@ -329,9 +329,7 @@
|
|||||||
<string name="video_size_help">Size of transmitted video frames (width x height).
|
<string name="video_size_help">Size of transmitted video frames (width x height).
|
||||||
Factory default is 800x600.</string>
|
Factory default is 800x600.</string>
|
||||||
<string name="android_settings">Android Settings</string>
|
<string name="android_settings">Android Settings</string>
|
||||||
<string name="show_android_contacts">Show Android Contacts</string>
|
<string name="contacts_help">Chooses if baresip contacts, Android contacts, or both will be used.</string>
|
||||||
<string name="show_android_contacts_help">If checked, Android contacts are shown when Contacts
|
|
||||||
button is touched.</string>
|
|
||||||
<string name="debug">Debug</string>
|
<string name="debug">Debug</string>
|
||||||
<string name="debug_help">If checked, provides debug and info level log messages to Logcat.</string>
|
<string name="debug_help">If checked, provides debug and info level log messages to Logcat.</string>
|
||||||
<string name="sip_trace">SIP Trace</string>
|
<string name="sip_trace">SIP Trace</string>
|
||||||
@ -356,8 +354,7 @@
|
|||||||
<string name="invalid_contact">Invalid contact name \'%1$s\'</string>
|
<string name="invalid_contact">Invalid contact name \'%1$s\'</string>
|
||||||
<string name="contact_already_exists">Contact \'%1$s\' already exists.</string>
|
<string name="contact_already_exists">Contact \'%1$s\' already exists.</string>
|
||||||
<string name="invalid_contact_uri">Invalid SIP URI</string>
|
<string name="invalid_contact_uri">Invalid SIP URI</string>
|
||||||
<string name="android" translatable="false">Android</string>
|
<string name="android_contact_help">If checked, this contact is added to Android contacts.</string>
|
||||||
<string name="android_contact_help">If checked, this contact is available also in Android contacts.</string>
|
|
||||||
<string name="avatar_image">Profile image</string>
|
<string name="avatar_image">Profile image</string>
|
||||||
<!-- Contacts Activity -->
|
<!-- Contacts Activity -->
|
||||||
<string name="contacts">Contacts</string>
|
<string name="contacts">Contacts</string>
|
||||||
@ -392,6 +389,9 @@
|
|||||||
<string name="dots" translatable="false">…</string>
|
<string name="dots" translatable="false">…</string>
|
||||||
<string name="bullet_item" translatable="false">\u2022 %1$s</string>
|
<string name="bullet_item" translatable="false">\u2022 %1$s</string>
|
||||||
<string name="invalid_sip_or_tel_uri">Invalid SIP or tel URI \'%1$s\'</string>
|
<string name="invalid_sip_or_tel_uri">Invalid SIP or tel URI \'%1$s\'</string>
|
||||||
|
<string name="baresip" translatable="false">baresip</string>
|
||||||
|
<string name="android" translatable="false">Android</string>
|
||||||
|
<string name="both">Both</string>
|
||||||
<!-- Main Activity -->
|
<!-- Main Activity -->
|
||||||
<string name="backup">Backup</string>
|
<string name="backup">Backup</string>
|
||||||
<string name="restore">Restore</string>
|
<string name="restore">Restore</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user