Added possibility to mark contact as favorite

This commit is contained in:
Juha Heinanen
2023-11-02 10:00:24 +02:00
parent 28da3c8fa1
commit ae46ee3b04
8 changed files with 96 additions and 35 deletions

View File

@ -69,7 +69,7 @@ class BaresipService: Service() {
private lateinit var wifiLock: WifiManager.WifiLock
private lateinit var bluetoothReceiver: BroadcastReceiver
private lateinit var hotSpotReceiver: BroadcastReceiver
private lateinit var contentObserver: ContentObserver
private lateinit var androidContactsObserver: ContentObserver
private lateinit var stopState: String
private lateinit var quitTimer: CountDownTimer
@ -82,7 +82,7 @@ class BaresipService: Service() {
private var hotSpotIsEnabled = false
private var hotSpotAddresses = mapOf<String, String>()
private var mediaPlayer: MediaPlayer? = null
private var contentObserverRegistered = false
private var androidContactsObserverRegistered = false
private var isServiceClean = false
@SuppressLint("WakelockTimeout")
@ -318,9 +318,9 @@ class BaresipService: Service() {
this.registerReceiver(bluetoothReceiver, filter)
}
contentObserver = object : ContentObserver(null) {
androidContactsObserver = object : ContentObserver(null) {
override fun onChange(self: Boolean) {
Log.d(TAG, "Contacts change")
Log.d(TAG, "Android contacts change")
if (contactsMode != "baresip") {
Contact.loadAndroidContacts(this@BaresipService.applicationContext)
Contact.contactsUpdate()
@ -412,7 +412,7 @@ class BaresipService: Service() {
Contact.restoreBaresipContacts()
if (contactsMode != "baresip") {
Contact.loadAndroidContacts(applicationContext)
registerContentObserver()
registerAndroidContactsObserver()
}
Contact.contactsUpdate()
@ -470,11 +470,11 @@ class BaresipService: Service() {
}
"Start Content Observer" -> {
registerContentObserver()
registerAndroidContactsObserver()
}
"Stop Content Observer" -> {
unRegisterContentObserver()
unRegisterAndroidContactsObserver()
}
"Call Answer" -> {
@ -1493,21 +1493,21 @@ class BaresipService: Service() {
}
}
private fun registerContentObserver() {
if (!contentObserverRegistered)
private fun registerAndroidContactsObserver() {
if (!androidContactsObserverRegistered)
try {
contentResolver.registerContentObserver(ContactsContract.Contacts.CONTENT_URI,
true, contentObserver)
contentObserverRegistered = true
true, androidContactsObserver)
androidContactsObserverRegistered = true
} catch (e: SecurityException) {
Log.i(TAG, "No Contacts permission")
}
}
private fun unRegisterContentObserver() {
if (contentObserverRegistered) {
contentResolver.unregisterContentObserver(contentObserver)
contentObserverRegistered = false
private fun unRegisterAndroidContactsObserver() {
if (androidContactsObserverRegistered) {
contentResolver.unregisterContentObserver(androidContactsObserver)
androidContactsObserverRegistered = false
}
}
@ -1529,8 +1529,8 @@ class BaresipService: Service() {
proximityWakeLock.release()
if (this::wifiLock.isInitialized)
wifiLock.release()
if (this::contentObserver.isInitialized)
contentResolver.unregisterContentObserver(contentObserver)
if (this::androidContactsObserver.isInitialized)
contentResolver.unregisterContentObserver(androidContactsObserver)
isServiceClean = true
}
}

View File

@ -12,7 +12,8 @@ import java.util.ArrayList
sealed class Contact {
class BaresipContact(var name: String, var uri: String, var color: Int, val id: Long): Contact() {
class BaresipContact(var name: String, var uri: String, var color: Int, val id: Long,
var favorite: Boolean): Contact() {
var avatarImage: Bitmap? = null
}
@ -110,7 +111,8 @@ sealed class Contact {
fun saveBaresipContacts() {
var contents = ""
for (c in BaresipService.baresipContacts)
contents += "\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color}\n"
contents += "\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color}" +
";favorite=${if (c.favorite) "yes" else "no"}\n"
Utils.putFileContents(BaresipService.filesPath + "/contacts",
contents.toByteArray())
}
@ -196,8 +198,9 @@ sealed class Contact {
idValue.toLong()
else
baseId + contactNo
val favorite = Utils.paramValue(params, "favorite" ) == "yes"
Log.d(TAG, "Restoring contact $name, $uri, $color, $id")
val contact = BaresipContact(name, uri, color, id)
val contact = BaresipContact(name, uri, color, id, favorite)
val avatarFilePath = BaresipService.filesPath + "/$id.png"
if (File(avatarFilePath).exists()) {
try {
@ -254,7 +257,7 @@ sealed class Contact {
private fun sortContacts() {
BaresipService.contacts.sortBy{ when (it) {
is BaresipContact -> "1" + it.name
is BaresipContact -> if (it.favorite) "0" + it.name else "1" + it.name
is AndroidContact -> if (it.favorite) "0" + it.name else "1" + it.name
}}
}

View File

@ -36,6 +36,7 @@ class ContactActivity : AppCompatActivity() {
private lateinit var cardImageAvatarView: ImageView
private lateinit var nameView: EditText
private lateinit var uriView: EditText
private lateinit var favoriteCheck: CheckBox
private lateinit var androidCheck: CheckBox
private lateinit var menu: Menu
@ -65,6 +66,7 @@ class ContactActivity : AppCompatActivity() {
cardImageAvatarView = binding.ImageAvatar
nameView = binding.Name
uriView = binding.Uri
favoriteCheck = binding.Favorite
androidCheck = binding.Android
newContact = intent.getBooleanExtra("new", false)
@ -87,6 +89,7 @@ class ContactActivity : AppCompatActivity() {
else
uriView.setText(uri)
uOrI = uri
favoriteCheck.isChecked = false
if ((BaresipService.contactsMode == "android")) {
androidCheck.isChecked = true
androidCheck.isClickable = false
@ -109,6 +112,7 @@ class ContactActivity : AppCompatActivity() {
title = name
nameView.setText(name)
uriView.setText(contact.uri)
favoriteCheck.isChecked = contact.favorite
uOrI = index.toString()
}
@ -250,13 +254,14 @@ class ContactActivity : AppCompatActivity() {
BaresipService.activities.removeAt(0)
return true
} else {
contact = Contact.BaresipContact(newName, newUri, color, id)
contact = Contact.BaresipContact(newName, newUri, color, id, favoriteCheck.isChecked)
}
} else {
contact = Contact.contacts()[index] as Contact.BaresipContact
contact.uri = newUri
contact.name = newName
contact.color = color
contact.favorite = favoriteCheck.isChecked
}
when (newAvatar) {
@ -286,7 +291,8 @@ class ContactActivity : AppCompatActivity() {
BaresipService.activities.remove("contact,$newContact,$uOrI")
val i = Intent(this, MainActivity::class.java)
i.putExtra("name", newName)
if (androidCheck.isChecked && contact.favorite)
i.putExtra("name", newName)
setResult(Activity.RESULT_OK, i)
finish()
}
@ -384,6 +390,7 @@ class ContactActivity : AppCompatActivity() {
.withValue(Data.MIMETYPE, mimeType)
.withValue(Data.DATA1, contact.uri.substringAfter(":"))
.build())
if (contact.avatarImage != null) {
val photoData: ByteArray? = bitmapToPNGByteArray(contact.avatarImage!!)
if (photoData != null) {
@ -443,7 +450,7 @@ class ContactActivity : AppCompatActivity() {
return try {
contentResolver.update(ContactsContract.Data.CONTENT_URI, contentValues, where, null)
} catch (e: Exception) {
Log.e(TAG, "Adding of SIP URI $uri failed")
Log.e(TAG, "Update of Android URI $uri failed")
0
}
}

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Typeface
import android.os.Bundle
import android.os.SystemClock
import android.provider.ContactsContract
@ -65,6 +66,10 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
viewHolder.nameView.text = contact.name
viewHolder.nameView.textSize = 20f
if (contact.favorite)
viewHolder.nameView.setTypeface(null, Typeface.ITALIC)
else
viewHolder.nameView.setTypeface(null, Typeface.NORMAL)
viewHolder.nameView.setPadding(6, 6, 0, 6)
if (aor != "") {
@ -139,6 +144,10 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
viewHolder.nameView.text = contact.name
viewHolder.nameView.textSize = 20f
if (contact.favorite)
viewHolder.nameView.setTypeface(null, Typeface.ITALIC)
else
viewHolder.nameView.setTypeface(null, Typeface.NORMAL)
viewHolder.nameView.setPadding(6, 6, 0, 6)
viewHolder.nameView.setOnClickListener {
@ -153,13 +162,7 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList<C
}
}
if (contact.favorite) {
viewHolder.actionView.setImageResource(R.drawable.star)
viewHolder.actionView.visibility = View.VISIBLE
} else {
viewHolder.actionView.visibility = View.GONE
}
viewHolder.actionView.visibility = View.GONE
}
viewHolder.nameView.setOnLongClickListener {

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.content.*
import android.os.Bundle
import android.os.SystemClock
import android.provider.ContactsContract
import androidx.appcompat.app.AppCompatActivity
import android.view.MenuItem
import androidx.activity.OnBackPressedCallback
@ -16,6 +17,7 @@ class ContactsActivity : AppCompatActivity() {
private lateinit var binding: ActivityContactsBinding
private lateinit var clAdapter: ContactListAdapter
private lateinit var aor: String
private var newAndroidName: String? = null
private var lastClick: Long = 0
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
@ -38,15 +40,31 @@ class ContactsActivity : AppCompatActivity() {
listView.adapter = clAdapter
listView.isLongClickable = true
val contactObserver = Observer<Long> {
val androidContactsObserver = Observer<Long> {
if (newAndroidName != null) {
val contentValues = ContentValues()
contentValues.put(ContactsContract.Contacts.STARRED, 1)
try {
this.contentResolver.update(
ContactsContract.RawContacts.CONTENT_URI, contentValues,
ContactsContract.Contacts.DISPLAY_NAME + "='" + newAndroidName + "'", null
)
} catch (e: Exception) {
Log.e(TAG, "Update of Android favorite failed")
}
newAndroidName = null
}
clAdapter.notifyDataSetChanged()
}
BaresipService.contactUpdate.observe(this, contactObserver)
BaresipService.contactUpdate.observe(this, androidContactsObserver)
val contactRequest =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK)
clAdapter.notifyDataSetChanged()
if (it.resultCode == RESULT_OK) {
if (it.data != null && it.data!!.hasExtra("name"))
newAndroidName = it.data!!.getStringExtra("name")
}
clAdapter.notifyDataSetChanged()
}
val plusButton = binding.plusButton

View File

@ -88,11 +88,38 @@
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/FavoriteTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/Favorite"
android:textSize="18sp"
android:text="@string/favorite" >
</TextView>
<CheckBox
android:id="@+id/Favorite"
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
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/AndroidTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/Android"
android:textSize="18sp"
android:text="@string/android" >
@ -102,6 +129,7 @@
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>

View File

@ -429,6 +429,7 @@
<string name="contact_name">Nimi</string>
<string name="sip_or_tel_uri">SIP tai tel URI</string>
<string name="user_domain_or_number">käyttäjä@domain tai puhelinnumero</string>
<string name="favorite">Suosikki</string>
<string name="invalid_contact">Virheellinen yhteystiedon nimi \'%1$s\'</string>
<string name="contact_already_exists">Yhteystieto \'%1$s\' on jo olemassa.</string>
<string name="invalid_contact_uri">Virheellinen SIP URI \'%1$s\'</string>

View File

@ -399,6 +399,7 @@
<string name="contact_name">Name</string>
<string name="sip_or_tel_uri">SIP or tel URI</string>
<string name="user_domain_or_number">user@domain or telephone number</string>
<string name="favorite">Favorite</string>
<string name="invalid_contact">Invalid contact name \'%1$s\'</string>
<string name="contact_already_exists">Contact \'%1$s\' already exists.</string>
<string name="invalid_contact_uri">Invalid SIP URI</string>