From a262827e3a22c331f78191134f85e5f82fed0740 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Mon, 25 Jan 2021 09:50:12 +0200 Subject: [PATCH] Allow exporting of baresip contacts to Android contacts --- app/src/main/AndroidManifest.xml | 2 + .../main/kotlin/com/tutpro/baresip/Contact.kt | 6 +- .../com/tutpro/baresip/ContactActivity.kt | 55 ++++++++++++------- .../com/tutpro/baresip/ContactListAdapter.kt | 6 +- .../kotlin/com/tutpro/baresip/MainActivity.kt | 2 +- .../main/kotlin/com/tutpro/baresip/Utils.kt | 21 ++++--- app/src/main/res/values-fi/strings.xml | 38 +++++++------ app/src/main/res/values/strings.xml | 3 +- 8 files changed, 79 insertions(+), 54 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 77900afc..8f455366 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,8 @@ + + diff --git a/app/src/main/kotlin/com/tutpro/baresip/Contact.kt b/app/src/main/kotlin/com/tutpro/baresip/Contact.kt index 42229b96..57e343e7 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Contact.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Contact.kt @@ -22,7 +22,7 @@ class Contact(var name: String, var uri: String, var color: Int, val id: Long) { fun save(): Boolean { var contents = "" for (c in BaresipService.contacts) contents += - "\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color}\n" + "\"${c.name}\" <${c.uri}>;id=${c.id};color=${c.color};android=${c.androidContact}\n" return Utils.putFileContents(BaresipService.filesPath + "/contacts", contents.toByteArray()) } @@ -49,14 +49,16 @@ class Contact(var name: String, var uri: String, var color: Int, val id: Long) { color = colorValue.toInt() else color = Utils.randomColor() + val androidContact = Utils.paramValue(params, "android" ) == "true" val idValue = Utils.paramValue(params, "id" ) val id: Long if (idValue != "") id = idValue.toLong() else id = baseId + contactNo - Log.d("Baresip", "Restoring contact $name, $uri, $color, $id") + Log.d("Baresip", "Restoring contact $name, $uri, $color, $id, $androidContact") val contact = Contact(name, uri, color, id) + contact.androidContact = androidContact val avatarFilePath = BaresipService.filesPath + "/$id.png" if (File(avatarFilePath).exists()) { try { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt index 4d5ffa8d..6c629e1d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt @@ -6,6 +6,7 @@ import android.content.ContentProviderOperation import android.content.ContentValues import android.content.Context import android.content.Intent +import android.content.pm.PackageManager import android.database.Cursor import android.graphics.Bitmap import android.graphics.BitmapFactory @@ -36,6 +37,7 @@ class ContactActivity : AppCompatActivity() { private lateinit var nameView: EditText private lateinit var uriView: EditText private lateinit var androidCheck: CheckBox + private lateinit var menu: Menu private var newContact = false private var newAvatar = "" @@ -168,12 +170,13 @@ class ContactActivity : AppCompatActivity() { } - override fun onCreateOptionsMenu(menu: Menu): Boolean { + override fun onCreateOptionsMenu(optionsMenu: Menu): Boolean { - super.onCreateOptionsMenu(menu) + super.onCreateOptionsMenu(optionsMenu) val inflater = menuInflater - inflater.inflate(R.menu.check_icon, menu) + inflater.inflate(R.menu.check_icon, optionsMenu) + menu = optionsMenu return true } @@ -259,7 +262,8 @@ class ContactActivity : AppCompatActivity() { Contact.contacts().sortBy { Contact -> Contact.name } - if (Utils.checkPermission(this, Manifest.permission.WRITE_CONTACTS)) { + if (Utils.checkPermission(this, Manifest.permission.READ_CONTACTS + + "|" + Manifest.permission.WRITE_CONTACTS)) { if (contact.androidContact) addOrUpdateAndroidContact(this, contact) else @@ -267,9 +271,9 @@ class ContactActivity : AppCompatActivity() { deleteAndroidContact(this, contact) } else { if (contact.androidContact) { - Utils.requestPermission(this, - "Manifest.permission.READ_CONTACTS,Manifest.permission.WRITE_CONTACTS", - MainActivity.CONTACT_PERMISSION_REQUEST_CODE) + Utils.requestPermission(this, Manifest.permission.READ_CONTACTS + + "|" + Manifest.permission.WRITE_CONTACTS, + MainActivity.CONTACTS_PERMISSION_REQUEST_CODE) return false } } @@ -297,6 +301,22 @@ class ContactActivity : AppCompatActivity() { } + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, + grantResults: IntArray) { + + when (requestCode) { + + MainActivity.CONTACTS_PERMISSION_REQUEST_CODE -> + if (grantResults.isNotEmpty() && permissions.size == grantResults.size) { + for (res in grantResults) + if (res != PackageManager.PERMISSION_GRANTED) + return + menu.performIdentifierAction(R.id.checkIcon, 0) + } + } + + } + override fun onBackPressed() { BaresipService.activities.remove("contact,$newContact,$uOrI") @@ -309,10 +329,8 @@ class ContactActivity : AppCompatActivity() { fun onClick(v: View) { when (v) { - binding.AndroidTitle -> { - Utils.alertView(this, getString(R.string.android), - getString(R.string.android_contact_help)) - } + binding.AndroidTitle -> + Utils.alertView(this, getString(R.string.android), getString(R.string.android_contact_help)) } } @@ -374,7 +392,6 @@ class ContactActivity : AppCompatActivity() { } private fun addAndroidContact(ctx: Context, contact: Contact): Boolean { - val cameraRotationMatrix = Matrix() val ops = ArrayList() val rawContactInsertIndex = ops.size ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) @@ -393,13 +410,8 @@ class ContactActivity : AppCompatActivity() { .withValue(Data.DATA1, contact.uri.substringAfter(":")) .build()) if (contact.avatarImage != null) { - cameraRotationMatrix.postRotate(180F) - val rotatedPhoto = Bitmap.createBitmap(contact.avatarImage!!, 0, 0, - contact.avatarImage!!.width, contact.avatarImage!!.height, - cameraRotationMatrix, false); - val photoData: ByteArray? = bitmapToPNGByteArray(rotatedPhoto) + val photoData: ByteArray? = bitmapToPNGByteArray(contact.avatarImage!!) if (photoData != null) { - Log.d("Baresip", "Adding photo") ops.add(ContentProviderOperation .newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex) @@ -420,8 +432,7 @@ class ContactActivity : AppCompatActivity() { private fun updateAndroidContact(ctx: Context, contactId: Long, contact: Contact) { val ops = ArrayList() val selection = ContactsContract.Data.CONTACT_ID + "='" + contactId.toString() + - "' AND " + - Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'" + "' AND " + Data.MIMETYPE + "='" + CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'" if (contact.avatarImage != null) { val stream = ByteArrayOutputStream() contact.avatarImage!!.compress(Bitmap.CompressFormat.PNG, 100, stream) @@ -441,7 +452,7 @@ class ContactActivity : AppCompatActivity() { Log.e("Baresip", "Update of contact $contactId failed") } val contentValues = ContentValues() - contentValues.put(ContactsContract.Data.DATA1, contact.uri) + contentValues.put(ContactsContract.Data.DATA1, contact.uri.substringAfter("sip:")) val where = ContactsContract.Data.CONTACT_ID + "=?" + " AND " + Data.MIMETYPE + "=?" val args = arrayOf((contactId).toString(), CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) ctx.contentResolver.update(ContactsContract.Data.CONTENT_URI, contentValues, where, args) @@ -463,6 +474,8 @@ class ContactActivity : AppCompatActivity() { companion object { + var contact: Contact? = null + fun deleteAndroidContact(ctx: Context, contact: Contact): Int { return ctx.contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.Contacts.DISPLAY_NAME + "='" + contact.name + "'", diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt index 3e6b4e36..852e368a 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt @@ -1,5 +1,6 @@ package com.tutpro.baresip +import android.Manifest import android.app.Activity import android.content.Context import android.content.DialogInterface @@ -126,9 +127,10 @@ class ContactListAdapter(private val ctx: Context, private val rows: ArrayList
  • Pisteen kosketus johtaa suoraan tilin asetuksiin.
  • Pyyhkäisy alas aikaansaa parhaillaan näkyvissä olevan tilin uudelleen rekisteröinnin.
  • -
  • Voit lisätä puheluiden ja viestien kohteet kontakteihin pitkällä kosketuksella.
  • -
  • Pitkillä kosketuksilla voi myös poistaa puheluita, viestiketjuja, viestejä ja kontakteja.
  • -
  • Voit lisätä/poistaa kontaktin avatar-kuvan koskettamalla kontaktin ikonia lyhyesti/pitkästi.
  • +
  • Voit lisätä puheluiden ja viestien kohteet yhteystietoihin pitkällä kosketuksella.
  • +
  • Pitkillä kosketuksilla voi myös poistaa puheluita, viestiketjuja, viestejä ja yhteystietoja.
  • +
  • Voit lisätä/poistaa yhteystiedon avatar-kuvan koskettamalla yhteystiedon ikonia lyhyesti/pitkästi.
  • Voit valita edellisen puhelun uudelleen koskettamalla virheää luuria silloin, kun puhelun kohde on tyhjä.
  • Tunnetut ongelmat

    @@ -55,9 +55,9 @@ (rekisteröintiä ei ole aktivoitu).
  • Pisteen kosketus johtaa suoraan tilin asetuksiin.
  • Pyyhkäisy alas aikaansaa parhaillaan näkyvissä olevan tilin uudelleen rekisteröinnin.
  • -
  • Voit lisätä puheluiden ja viestien kohteet kontakteihin pitkällä kosketuksella.
  • -
  • Pitkillä kosketuksilla voi myös poistaa puheluita, viestiketjuja, viestejä ja kontakteja.
  • -
  • Voit lisätä/poistaa kontaktin avatar-kuvan koskettamalla kontaktin ikonia lyhyesti/pitkästi.
  • +
  • Voit lisätä puheluiden ja viestien kohteet yhteystietoihin pitkällä kosketuksella.
  • +
  • Pitkillä kosketuksilla voi myös poistaa puheluita, viestiketjuja, viestejä ja yhteystietoja.
  • +
  • Voit lisätä/poistaa yhteystiedon avatar-kuvan koskettamalla yhteystiedon ikonia lyhyesti/pitkästi.
  • Voit valita edellisen puhelun uudelleen koskettamalla virheää luuria silloin, kun puhelun kohde on tyhjä.
  • Jos et puhelun aikana kuule, mitä toinen sanoo, kasvata median volyymia laitteessa @@ -222,7 +222,7 @@ Haluatko soittaa tai lähettää viestin kohteeseen \'%1$s\'? - Haluatko luoda uuden kontaktin \'%1$s\' tai poistaa + Haluatko luoda uuden yhteystiedon \'%1$s\' tai poistaa %2$s puheluhistoriasta? Haluatko poistaa \'%1$s\' %2$s puheluhistoriasta? @@ -235,9 +235,9 @@ Viestiketju %1$s Uusi viesti Haluatko poistaa viestin tai - luoda uuden kontaktin \'%1$s\'? + luoda uuden yhteystiedon \'%1$s\'? Haluatko poistaa viestin? - Lisää kontakti + Lisää yhteystieto Viestin lähetys epäonnistui Epäonnistui @@ -247,7 +247,7 @@ Uusi viestin kohde Virheellinen SIP URI Haluatko poistaa viestiketjun tai - luoda uuden kontaktin \'%1$s\'? + luoda uuden yhteystiedon \'%1$s\'? Haluatko poistaa viestiketjun \'%1$s\'? Tyhjennä Haluatko tyhjentää tilin \'%1$s\' viestihistorian? @@ -333,19 +333,21 @@ käyttöön. Käynnistä nyt? - Kontakti - Uusi kontakti + Yhteystieto + Uusi yhteystieto Nimi - Virheellinen kontaktin nimi \'%1$s\' - Kontakti \'%1$s\' on jo olemassa. + Virheellinen yhteystiedon nimi \'%1$s\' + Yhteystieto \'%1$s\' on jo olemassa. Virheellinen SIP URI \'%1$s\' + Jos merkitty, tämä yhteystieto näkyy myös Androidin + yhteystiedoissa. - Kontaktit + Yhteystiedot Haluatko soittaa tai lähettää - viestin kontaktille \'%1$s\'? + viestin ositteeseen \'%1$s\'? Lähetä viesti - Haluatko poistaa kontaktin \'%1$s\'? - Kontaktiesi enimmäismäärä %1$d on ylittynyt. + Haluatko poistaa yhteystiedon \'%1$s\'? + Yhteystietojesi enimmäismäärä %1$d on ylittynyt. Varoitus Tieto diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2e44867e..94a31ba8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -302,8 +302,7 @@ Contact \'%1$s\' already exists. Invalid SIP URI Android - This information is exposed in Android contacts. - + if checked, this contact is available also in Android contacts. Contacts Do you want to call or send message to \'%1$s\'?