Added possibility to use Android contacts
This commit is contained in:
@ -1,8 +1,9 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.net.Uri
|
||||
import java.util.ArrayList
|
||||
|
||||
class AndroidContact(val id: Long, var name: String, var color: Int, val thumbnailUri: String?) {
|
||||
class AndroidContact(val id: Long, var name: String, var color: Int, var thumbnailUri: Uri?) {
|
||||
|
||||
val uris = ArrayList<String>()
|
||||
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.net.toUri
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tutpro.baresip.Utils.showSnackBar
|
||||
import com.tutpro.baresip.databinding.ActivityAndroidContactBinding
|
||||
|
||||
class AndroidContactActivity : AppCompatActivity() {
|
||||
@ -28,7 +23,6 @@ class AndroidContactActivity : AppCompatActivity() {
|
||||
private lateinit var nameView: TextView
|
||||
private lateinit var ulAdapter: AndroidUriListAdapter
|
||||
private lateinit var aor: String
|
||||
private lateinit var requestPermissionsLauncher: ActivityResultLauncher<Array<String>>
|
||||
|
||||
private var index = 0
|
||||
private var color = 0
|
||||
@ -49,7 +43,7 @@ class AndroidContactActivity : AppCompatActivity() {
|
||||
cardImageAvatarView = binding.ImageAvatar
|
||||
nameView = binding.Name
|
||||
|
||||
val contact = AndroidContactsActivity.androidContacts[index]
|
||||
val contact = BaresipService.androidContacts[index]
|
||||
val name = contact.name
|
||||
color = contact.color
|
||||
id = contact.id
|
||||
@ -69,53 +63,6 @@ class AndroidContactActivity : AppCompatActivity() {
|
||||
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
requestPermissionsLauncher =
|
||||
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<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) {
|
||||
when {
|
||||
ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.READ_CONTACTS) -> {
|
||||
layout.showSnackBar(
|
||||
binding.root,
|
||||
getString(R.string.no_android_contacts),
|
||||
Snackbar.LENGTH_INDEFINITE,
|
||||
getString(R.string.ok)
|
||||
) {
|
||||
requestPermissionsLauncher.launch(permissions)
|
||||
}
|
||||
}
|
||||
ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||
Manifest.permission.WRITE_CONTACTS) -> {
|
||||
layout.showSnackBar(
|
||||
binding.root,
|
||||
getString(R.string.no_android_contacts),
|
||||
Snackbar.LENGTH_INDEFINITE,
|
||||
getString(R.string.ok)
|
||||
) {
|
||||
requestPermissionsLauncher.launch(permissions)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
requestPermissionsLauncher.launch(permissions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
||||
if (BaresipService.activities.indexOf("android contact,$aor,$index") == -1) return true
|
||||
@ -151,10 +98,10 @@ class AndroidContactActivity : AppCompatActivity() {
|
||||
textAvatarView.text = "${name[0]}"
|
||||
}
|
||||
|
||||
private fun showImageAvatar(thumbNailUri: String) {
|
||||
private fun showImageAvatar(thumbNailUri: Uri) {
|
||||
textAvatarView.visibility = View.GONE
|
||||
cardAvatarView.visibility = View.VISIBLE
|
||||
cardImageAvatarView.setImageURI(thumbNailUri.toUri())
|
||||
cardImageAvatarView.setImageURI(thumbNailUri)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.core.net.toUri
|
||||
|
||||
class AndroidContactListAdapter(private val ctx: Context,
|
||||
private val rows: ArrayList<AndroidContact>,
|
||||
@ -45,7 +44,7 @@ class AndroidContactListAdapter(private val ctx: Context,
|
||||
|
||||
val thumbNailUri = contact.thumbnailUri
|
||||
if (thumbNailUri != null) {
|
||||
viewHolder.imageAvatarView.setImageURI(thumbNailUri.toUri())
|
||||
viewHolder.imageAvatarView.setImageURI(thumbNailUri)
|
||||
} else {
|
||||
contact.color = Utils.randomColor()
|
||||
viewHolder.textAvatarView.background.setTint(contact.color)
|
||||
|
||||
@ -1,35 +1,64 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.database.Cursor
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.provider.ContactsContract
|
||||
import android.view.Menu
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.net.toUri
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tutpro.baresip.Utils.showSnackBar
|
||||
import com.tutpro.baresip.databinding.ActivityAndroidContactsBinding
|
||||
|
||||
class AndroidContactsActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityAndroidContactsBinding
|
||||
private lateinit var layout: RelativeLayout
|
||||
private lateinit var clAdapter: AndroidContactListAdapter
|
||||
private lateinit var aor: String
|
||||
private var lastSwap: Long = 0
|
||||
private lateinit var permissionsLauncher: ActivityResultLauncher<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
|
||||
|
||||
getAndroidContacts(this)
|
||||
clAdapter = AndroidContactListAdapter(this, androidContacts, aor)
|
||||
permissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||
var allowed = true
|
||||
permissions.entries.forEach {
|
||||
allowed = allowed && it.value
|
||||
}
|
||||
if (allowed) {
|
||||
fetchAndroidContacts(this)
|
||||
clAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23 && !Utils.checkPermissions(this, permissions))
|
||||
requestPermissions(permissions, CONTACT_PERMISSION_REQUEST_CODE)
|
||||
else
|
||||
fetchAndroidContacts(this)
|
||||
|
||||
clAdapter = AndroidContactListAdapter(this, BaresipService.androidContacts, aor)
|
||||
listView.adapter = clAdapter
|
||||
|
||||
Utils.addActivity("android contacts,$aor")
|
||||
@ -45,7 +74,7 @@ class AndroidContactsActivity : AppCompatActivity() {
|
||||
|
||||
when (item.itemId) {
|
||||
|
||||
R.id.swapContactsIcon -> {
|
||||
R.id.swapIcon -> {
|
||||
if (SystemClock.elapsedRealtime() - lastSwap > 1000) {
|
||||
lastSwap = SystemClock.elapsedRealtime()
|
||||
BaresipService.activities.remove("android contacts,$aor")
|
||||
@ -76,46 +105,110 @@ class AndroidContactsActivity : AppCompatActivity() {
|
||||
|
||||
}
|
||||
|
||||
private fun getAndroidContacts(ctx: Context) {
|
||||
val projection = arrayOf(ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME,
|
||||
ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1,
|
||||
ContactsContract.Data.PHOTO_THUMBNAIL_URI)
|
||||
val selection =
|
||||
ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' OR " +
|
||||
ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'"
|
||||
Log.d(TAG, "******* selection = /$selection/")
|
||||
val cur: Cursor? = ctx.contentResolver.query(ContactsContract.Data.CONTENT_URI, projection,
|
||||
selection, null, null)
|
||||
val contacts = HashMap<Long, AndroidContact>()
|
||||
while (cur != null && cur.moveToNext()) {
|
||||
val id = cur.getLong(0)
|
||||
val name = cur.getString(1) // display name
|
||||
val mime = cur.getString(2) // type of data
|
||||
val data = cur.getString(3) // data
|
||||
val thumb = cur.getString(4) // thumbnail
|
||||
// Log.d(TAG, "****** $id - $name - $mime - $data - $thumb")
|
||||
val contact = if (contacts.containsKey(id))
|
||||
contacts[id]!!
|
||||
else
|
||||
AndroidContact(id, name, 0, thumb)
|
||||
if (mime == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
||||
contact.uris.add("tel:$data")
|
||||
else if (mime == ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
|
||||
contact.uris.add("sip:$data")
|
||||
else
|
||||
continue
|
||||
if (!contacts.containsKey(id))
|
||||
contacts[id] = contact
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cur?.close()
|
||||
androidContacts.clear()
|
||||
for ((_, value) in contacts)
|
||||
androidContacts.add(value)
|
||||
return
|
||||
}
|
||||
|
||||
companion object {
|
||||
val androidContacts = ArrayList<AndroidContact>()
|
||||
|
||||
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, 0, thumb)
|
||||
if (contact.name == "" && name != "")
|
||||
contact.name = name
|
||||
if (contact.thumbnailUri == null && thumb != null)
|
||||
contact.thumbnailUri = thumb
|
||||
if (mime == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
||||
contact.uris.add("tel:${data.filterNot{setOf('-', ' ').contains(it)}}")
|
||||
else if (mime == ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
|
||||
contact.uris.add("sip:$data")
|
||||
else
|
||||
continue
|
||||
if (!contacts.containsKey(id))
|
||||
contacts[id] = contact
|
||||
}
|
||||
cur?.close()
|
||||
BaresipService.androidContacts.clear()
|
||||
for ((_, value) in contacts)
|
||||
if (value.name != "")
|
||||
BaresipService.androidContacts.add(value)
|
||||
return
|
||||
}
|
||||
|
||||
fun findContact(uri: String): AndroidContact? {
|
||||
for (c in BaresipService.androidContacts)
|
||||
for (u in c.uris)
|
||||
if (Utils.uriMatch(u, uri))
|
||||
return c
|
||||
return null
|
||||
}
|
||||
|
||||
// Return contact name of uri or uri itself if contact with uri is not found
|
||||
fun contactName(uri: String): String {
|
||||
val userPart = Utils.uriUserPart(uri)
|
||||
return if (Utils.isTelNumber(userPart))
|
||||
findContact("tel:$userPart")?.name ?: uri
|
||||
else
|
||||
findContact(uri)?.name ?: uri
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -296,6 +296,7 @@ class BaresipService: Service() {
|
||||
this.registerReceiver(bluetoothReceiver, filter)
|
||||
}
|
||||
|
||||
AndroidContactsActivity.fetchAndroidContacts(this)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
@ -648,8 +649,7 @@ class BaresipService: Service() {
|
||||
PendingIntent.getActivity(applicationContext, CALL_REQ_CODE, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||
val caller = Utils.friendlyUri(ContactsActivity.contactName(peerUri),
|
||||
Utils.aorDomain(aor))
|
||||
val caller = Utils.friendlyUri(Utils.contactName(peerUri), Utils.aorDomain(aor))
|
||||
nb.setSmallIcon(R.drawable.ic_stat_call)
|
||||
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
||||
.setContentIntent(pi)
|
||||
@ -743,8 +743,7 @@ class BaresipService: Service() {
|
||||
PendingIntent.getActivity(applicationContext, TRANSFER_REQ_CODE,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||
val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]),
|
||||
Utils.aorDomain(aor))
|
||||
val target = Utils.friendlyUri(Utils.contactName(ev[1]), Utils.aorDomain(aor))
|
||||
nb.setSmallIcon(R.drawable.ic_stat_call)
|
||||
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
||||
.setContentIntent(pi)
|
||||
@ -820,8 +819,7 @@ class BaresipService: Service() {
|
||||
}
|
||||
if (!Utils.isVisible()) {
|
||||
if (missed) {
|
||||
val caller = Utils.friendlyUri(ContactsActivity.contactName(call.peerUri),
|
||||
Utils.aorDomain(aor))
|
||||
val caller = Utils.friendlyUri(Utils.contactName(call.peerUri), Utils.aorDomain(aor))
|
||||
val intent = Intent(applicationContext, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or
|
||||
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
@ -927,8 +925,7 @@ class BaresipService: Service() {
|
||||
PendingIntent.getActivity(applicationContext, MESSAGE_REQ_CODE, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
val nb = NotificationCompat.Builder(this, HIGH_CHANNEL_ID)
|
||||
val sender = Utils.friendlyUri(ContactsActivity.contactName(peer),
|
||||
Utils.aorDomain(ua.account.aor))
|
||||
val sender = Utils.friendlyUri(Utils.contactName(peer), Utils.aorDomain(ua.account.aor))
|
||||
nb.setSmallIcon(R.drawable.ic_stat_message)
|
||||
.setColor(ContextCompat.getColor(this, R.color.colorBaresip))
|
||||
.setContentIntent(pi)
|
||||
@ -1111,8 +1108,12 @@ class BaresipService: Service() {
|
||||
}
|
||||
|
||||
private fun requestAudioFocus(type: Int) {
|
||||
if (audioFocusRequest != null && audioFocusRequest!!.audioAttributesCompat.contentType == type)
|
||||
return
|
||||
if (audioFocusRequest != null) {
|
||||
if (audioFocusRequest!!.audioAttributesCompat.contentType == type)
|
||||
return
|
||||
else
|
||||
abandonAudioFocus()
|
||||
}
|
||||
val attributes = AudioAttributesCompat.Builder()
|
||||
.setUsage(AudioAttributesCompat.USAGE_VOICE_COMMUNICATION)
|
||||
.setContentType(type)
|
||||
@ -1418,6 +1419,7 @@ class BaresipService: Service() {
|
||||
val messageUpdate = MutableLiveData<Long>()
|
||||
val registrationUpdate = MutableLiveData<Long>()
|
||||
val contacts = ArrayList<Contact>()
|
||||
val androidContacts = ArrayList<AndroidContact>()
|
||||
val chatTexts: MutableMap<String, String> = mutableMapOf()
|
||||
val activities = mutableListOf<String>()
|
||||
var dnsServers = listOf<InetAddress>()
|
||||
|
||||
@ -2,7 +2,6 @@ package com.tutpro.baresip
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -12,8 +11,6 @@ import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
|
||||
import java.util.*
|
||||
|
||||
class CallListAdapter(private val ctx: Context, private val aor: String, private val rows: ArrayList<CallRow>) :
|
||||
ArrayAdapter<CallRow>(ctx, R.layout.call_row, rows) {
|
||||
|
||||
@ -44,23 +41,7 @@ class CallListAdapter(private val ctx: Context, private val aor: String, private
|
||||
|
||||
val callRow = rows[position]
|
||||
|
||||
val contact = ContactsActivity.findContact(callRow.peerUri)
|
||||
if (contact != null) {
|
||||
val avatarImage = contact.avatarImage
|
||||
if (avatarImage != null) {
|
||||
viewHolder.imageAvatarView.setImageBitmap(avatarImage)
|
||||
} else {
|
||||
viewHolder.textAvatarView.background.setTint(contact.color)
|
||||
if (contact.name.isNotEmpty())
|
||||
viewHolder.textAvatarView.text = "${contact.name[0]}"
|
||||
else
|
||||
viewHolder.textAvatarView.text = ""
|
||||
viewHolder.imageAvatarView.setImageBitmap(Utils.bitmapFromView(viewHolder.textAvatarView))
|
||||
}
|
||||
} else {
|
||||
val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.person_image)
|
||||
viewHolder.imageAvatarView.setImageBitmap(bitmap)
|
||||
}
|
||||
Utils.setAvatar(ctx, viewHolder.imageAvatarView, viewHolder.textAvatarView, callRow.peerUri)
|
||||
|
||||
viewHolder.directionsView.removeAllViews()
|
||||
var count = 1
|
||||
@ -81,7 +62,7 @@ class CallListAdapter(private val ctx: Context, private val aor: String, private
|
||||
if (count <= 3)
|
||||
viewHolder.etcView.text = ""
|
||||
|
||||
val contactName = ContactsActivity.contactName(callRow.peerUri)
|
||||
val contactName = Utils.contactName(callRow.peerUri)
|
||||
if (contactName.startsWith("sip:"))
|
||||
viewHolder.peerURIView.text = Utils.friendlyUri(contactName, Utils.aorDomain(callRow.aor))
|
||||
else
|
||||
|
||||
@ -50,7 +50,7 @@ class CallsActivity : AppCompatActivity() {
|
||||
|
||||
listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ ->
|
||||
val peerUri = uaHistory[pos].peerUri
|
||||
var peerName = ContactsActivity.contactName(peerUri)
|
||||
var peerName = Utils.contactName(peerUri)
|
||||
if (peerName.startsWith("sip:"))
|
||||
peerName = Utils.friendlyUri(peerName, Utils.aorDomain(aor))
|
||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||
@ -95,7 +95,7 @@ class CallsActivity : AppCompatActivity() {
|
||||
|
||||
listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ ->
|
||||
val peerUri = uaHistory[pos].peerUri
|
||||
val peerName = ContactsActivity.contactName(peerUri)
|
||||
val peerName = Utils.contactName(peerUri)
|
||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
|
||||
@ -63,7 +63,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
this@ChatActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
|
||||
|
||||
var chatPeer = ContactsActivity.contactName(peerUri)
|
||||
var chatPeer = Utils.contactName(peerUri)
|
||||
if (chatPeer.startsWith("sip:"))
|
||||
chatPeer = Utils.friendlyUri(chatPeer, Utils.aorDomain(aor))
|
||||
|
||||
@ -112,7 +112,7 @@ class ChatActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
val builder = AlertDialog.Builder(this@ChatActivity, R.style.Theme_AppCompat)
|
||||
if (ContactsActivity.contactName(peerUri) == peerUri)
|
||||
if (Utils.contactName(peerUri) == peerUri)
|
||||
with (builder) {
|
||||
setMessage(String.format(getString(R.string.long_message_question),
|
||||
chatPeer))
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
package com.tutpro.baresip
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Typeface
|
||||
import androidx.core.content.ContextCompat
|
||||
import android.text.format.DateUtils.isToday
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
|
||||
import java.util.*
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
class ChatListAdapter(private val ctx: Context, private val rows: ArrayList<Message>) :
|
||||
ArrayAdapter<Message>(ctx, R.layout.message, rows) {
|
||||
@ -43,26 +44,7 @@ class ChatListAdapter(private val ctx: Context, private val rows: ArrayList<Mess
|
||||
|
||||
val message = rows[position]
|
||||
|
||||
val contact = ContactsActivity.findContact(message.peerUri)
|
||||
val peer: String
|
||||
if (contact != null) {
|
||||
peer = contact.name
|
||||
val avatarImage = contact.avatarImage
|
||||
if (avatarImage != null) {
|
||||
viewHolder.imageAvatarView.setImageBitmap(avatarImage)
|
||||
} else {
|
||||
viewHolder.textAvatarView.background.setTint(contact.color)
|
||||
if (peer.isNotEmpty())
|
||||
viewHolder.textAvatarView.text = "${peer[0]}"
|
||||
else
|
||||
viewHolder.textAvatarView.text = ""
|
||||
viewHolder.imageAvatarView.setImageBitmap(Utils.bitmapFromView(viewHolder.textAvatarView))
|
||||
}
|
||||
} else {
|
||||
peer = Utils.friendlyUri(message.peerUri, message.aor)
|
||||
val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.person_image)
|
||||
viewHolder.imageAvatarView.setImageBitmap(bitmap)
|
||||
}
|
||||
Utils.setAvatar(ctx, viewHolder.imageAvatarView, viewHolder.textAvatarView, message.peerUri)
|
||||
|
||||
if ((message.direction == R.drawable.arrow_down_green) ||
|
||||
(message.direction == R.drawable.arrow_down_red))
|
||||
@ -70,7 +52,11 @@ class ChatListAdapter(private val ctx: Context, private val rows: ArrayList<Mess
|
||||
else
|
||||
viewHolder.layoutView.setBackgroundResource(R.drawable.message_out_bg)
|
||||
|
||||
viewHolder.peerView.text = peer
|
||||
val peerName = Utils.contactName(message.peerUri)
|
||||
viewHolder.peerView.text = if (peerName !=message.peerUri )
|
||||
peerName
|
||||
else
|
||||
Utils.friendlyUri(message.peerUri, message.aor)
|
||||
|
||||
val cal = GregorianCalendar()
|
||||
cal.timeInMillis = message.timeStamp
|
||||
|
||||
@ -95,7 +95,7 @@ class ChatsActivity: AppCompatActivity() {
|
||||
}
|
||||
|
||||
val builder = AlertDialog.Builder(this@ChatsActivity, R.style.Theme_AppCompat)
|
||||
val peer = ContactsActivity.contactName(uaMessages[pos].peerUri)
|
||||
val peer = Utils.contactName(uaMessages[pos].peerUri)
|
||||
if (peer.startsWith("sip:"))
|
||||
with (builder) {
|
||||
setMessage(String.format(getString(R.string.long_chat_question),
|
||||
|
||||
@ -8,10 +8,8 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
@ -528,13 +526,6 @@ class ConfigActivity : AppCompatActivity() {
|
||||
binding.AudioSettingsTitle.setOnClickListener {
|
||||
startActivity(Intent(this, AudioActivity::class.java))
|
||||
}
|
||||
binding.AndroidSettings.setOnClickListener {
|
||||
val i = Intent()
|
||||
i.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
i.data = Uri.parse("package:${applicationContext.packageName}")
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
|
||||
startActivity(i)
|
||||
}
|
||||
binding.DarkThemeTitle.setOnClickListener {
|
||||
Utils.alertView(this, getString(R.string.dark_theme),
|
||||
getString(R.string.dark_theme_help))
|
||||
|
||||
@ -33,7 +33,6 @@ import com.tutpro.baresip.databinding.ActivityContactBinding
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
|
||||
|
||||
class ContactActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityContactBinding
|
||||
|
||||
@ -74,7 +74,7 @@ class ContactsActivity : AppCompatActivity() {
|
||||
|
||||
when (item.itemId) {
|
||||
|
||||
R.id.swapContactsIcon -> {
|
||||
R.id.swapIcon -> {
|
||||
if (SystemClock.elapsedRealtime() - lastClick > 1000) {
|
||||
lastClick = SystemClock.elapsedRealtime()
|
||||
BaresipService.activities.remove("contacts,$aor")
|
||||
@ -117,9 +117,10 @@ class ContactsActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
fun findContact(uri: String): Contact? {
|
||||
for (c in Contact.contacts())
|
||||
for (c in Contact.contacts()) {
|
||||
if (Utils.uriMatch(c.uri, uri))
|
||||
return c
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@ -1105,8 +1105,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val call = Call.ofCallp(callp)!!
|
||||
val titleView = View.inflate(this, R.layout.alert_title, null) as TextView
|
||||
titleView.text = getString(R.string.transfer_request)
|
||||
val target = Utils.friendlyUri(ContactsActivity.contactName(ev[1]),
|
||||
Utils.aorDomain(aor))
|
||||
val target = Utils.friendlyUri(Utils.contactName(ev[1]), Utils.aorDomain(aor))
|
||||
with(AlertDialog.Builder(this)) {
|
||||
setCustomTitle(titleView)
|
||||
setMessage(String.format(getString(R.string.transfer_request_query),
|
||||
@ -1752,8 +1751,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val latest = NewCallHistory.aorLatestHistory(aor)
|
||||
if (latest != null)
|
||||
callUri.setText(
|
||||
Utils.friendlyUri(
|
||||
ContactsActivity.contactName(latest.peerUri), Utils.aorDomain(aor)
|
||||
Utils.friendlyUri(Utils.contactName(latest.peerUri), Utils.aorDomain(aor)
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -1799,7 +1797,7 @@ class MainActivity : AppCompatActivity() {
|
||||
else
|
||||
getString(R.string.outgoing_call_to_dots)
|
||||
callTimer.visibility = View.INVISIBLE
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerUri),
|
||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
callButton.visibility = View.INVISIBLE
|
||||
@ -1814,7 +1812,7 @@ class MainActivity : AppCompatActivity() {
|
||||
"incoming" -> {
|
||||
callTitle.text = getString(R.string.incoming_call_from_dots)
|
||||
callTimer.visibility = View.INVISIBLE
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerUri),
|
||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
callUri.setAdapter(null)
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
@ -1834,7 +1832,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
if (call.referTo != "") {
|
||||
callTitle.text = getString(R.string.transferring_call_to_dots)
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.referTo),
|
||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.referTo),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
transferButton.isEnabled = false
|
||||
} else {
|
||||
@ -1842,7 +1840,7 @@ class MainActivity : AppCompatActivity() {
|
||||
callTitle.text = getString(R.string.outgoing_call_to_dots)
|
||||
else
|
||||
callTitle.text = getString(R.string.incoming_call_from_dots)
|
||||
callUri.setText(Utils.friendlyUri(ContactsActivity.contactName(call.peerUri),
|
||||
callUri.setText(Utils.friendlyUri(Utils.contactName(call.peerUri),
|
||||
Utils.aorDomain(ua.account.aor)))
|
||||
transferButton.isEnabled = true
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class MessageListAdapter(private val ctx: Context, private val rows: ArrayList<M
|
||||
val peer: String = if (down) {
|
||||
lp.setMargins(0, 10, 75, 10)
|
||||
viewHolder.layoutView.setBackgroundResource(R.drawable.message_in_bg)
|
||||
val contactName = ContactsActivity.contactName(message.peerUri)
|
||||
val contactName = Utils.contactName(message.peerUri)
|
||||
if (contactName.startsWith("sip:") &&
|
||||
(Utils.uriHostPart(message.peerUri) == Utils.uriHostPart(message.aor)))
|
||||
Utils.uriUserPart(message.peerUri)
|
||||
|
||||
@ -7,6 +7,7 @@ import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Bitmap.createScaledBitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.net.*
|
||||
@ -22,6 +23,7 @@ import android.text.TextWatcher
|
||||
import android.text.format.DateUtils
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.annotation.RequiresApi
|
||||
@ -107,7 +109,7 @@ object Utils {
|
||||
|
||||
fun uriMatch(firstUri: String, secondUri: String): Boolean {
|
||||
if (firstUri.startsWith("tel:"))
|
||||
return firstUri == secondUri
|
||||
return firstUri == secondUri || firstUri.substringAfter(":") == uriUserPart(secondUri)
|
||||
if (firstUri.startsWith("sip:"))
|
||||
return uriUserPart(firstUri) == uriUserPart(secondUri) &&
|
||||
uriHostPart(firstUri) == uriHostPart(secondUri)
|
||||
@ -318,6 +320,49 @@ object Utils {
|
||||
name.lines().size == 1 && !name.contains('"')
|
||||
}
|
||||
|
||||
fun contactName(uri: String) : String {
|
||||
val name = ContactsActivity.contactName(uri)
|
||||
return if (name != uri)
|
||||
name
|
||||
else
|
||||
AndroidContactsActivity.contactName(uri)
|
||||
}
|
||||
|
||||
fun setAvatar(ctx: Context, imageView: ImageView, textView: TextView, uri: String) {
|
||||
val contact = ContactsActivity.findContact(uri)
|
||||
if (contact != null) {
|
||||
val avatarImage = contact.avatarImage
|
||||
if (avatarImage != null) {
|
||||
imageView.setImageBitmap(avatarImage)
|
||||
} else {
|
||||
textView.background.setTint(contact.color)
|
||||
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 {
|
||||
textView.background.setTint(androidContact.color)
|
||||
if (androidContact.name.isNotEmpty())
|
||||
textView.text = "${androidContact.name[0]}"
|
||||
else
|
||||
textView.text = ""
|
||||
imageView.setImageBitmap(bitmapFromView(textView))
|
||||
}
|
||||
} else {
|
||||
val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.person_image)
|
||||
imageView.setImageBitmap(bitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun checkIfName(name: String): Boolean {
|
||||
if ((name.length < 2) || !name.first().isLetter()) return false
|
||||
|
||||
10
app/src/main/res/drawable-anydpi/ic_action_call.xml
Normal file
10
app/src/main/res/drawable-anydpi/ic_action_call.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M6.54,5c0.06,0.89 0.21,1.76 0.45,2.59l-1.2,1.2c-0.41,-1.2 -0.67,-2.47 -0.76,-3.79h1.51m9.86,12.02c0.85,0.24 1.72,0.39 2.6,0.45v1.49c-1.32,-0.09 -2.59,-0.35 -3.8,-0.75l1.2,-1.19M7.5,3H4c-0.55,0 -1,0.45 -1,1 0,9.39 7.61,17 17,17 0.55,0 1,-0.45 1,-1v-3.49c0,-0.55 -0.45,-1 -1,-1 -1.24,0 -2.45,-0.2 -3.57,-0.57 -0.1,-0.04 -0.21,-0.05 -0.31,-0.05 -0.26,0 -0.51,0.1 -0.71,0.29l-2.2,2.2c-2.83,-1.45 -5.15,-3.76 -6.59,-6.59l2.2,-2.2c0.28,-0.28 0.36,-0.67 0.25,-1.02C8.7,6.45 8.5,5.25 8.5,4c0,-0.55 -0.45,-1 -1,-1z"/>
|
||||
</vector>
|
||||
20
app/src/main/res/drawable-anydpi/ic_action_swap.xml
Normal file
20
app/src/main/res/drawable-anydpi/ic_action_swap.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M21,5c-1.11,-0.35 -2.33,-0.5 -3.5,-0.5c-1.95,0 -4.05,0.4 -5.5,1.5c-1.45,-1.1 -3.55,-1.5 -5.5,-1.5S2.45,4.9 1,6v14.65c0,0.25 0.25,0.5 0.5,0.5c0.1,0 0.15,-0.05 0.25,-0.05C3.1,20.45 5.05,20 6.5,20c1.95,0 4.05,0.4 5.5,1.5c1.35,-0.85 3.8,-1.5 5.5,-1.5c1.65,0 3.35,0.3 4.75,1.05c0.1,0.05 0.15,0.05 0.25,0.05c0.25,0 0.5,-0.25 0.5,-0.5V6C22.4,5.55 21.75,5.25 21,5zM21,18.5c-1.1,-0.35 -2.3,-0.5 -3.5,-0.5c-1.7,0 -4.15,0.65 -5.5,1.5V8c1.35,-0.85 3.8,-1.5 5.5,-1.5c1.2,0 2.4,0.15 3.5,0.5V18.5z"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17.5,10.5c0.88,0 1.73,0.09 2.5,0.26V9.24C19.21,9.09 18.36,9 17.5,9c-1.7,0 -3.24,0.29 -4.5,0.83v1.66C14.13,10.85 15.7,10.5 17.5,10.5z"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M13,12.49v1.66c1.13,-0.64 2.7,-0.99 4.5,-0.99c0.88,0 1.73,0.09 2.5,0.26V11.9c-0.79,-0.15 -1.64,-0.24 -2.5,-0.24C15.8,11.66 14.26,11.96 13,12.49z"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M17.5,14.33c-1.7,0 -3.24,0.29 -4.5,0.83v1.66c1.13,-0.64 2.7,-0.99 4.5,-0.99c0.88,0 1.73,0.09 2.5,0.26v-1.52C19.21,14.41 18.36,14.33 17.5,14.33z"/>
|
||||
</vector>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 402 B |
Binary file not shown.
|
Before Width: | Height: | Size: 278 B |
Binary file not shown.
|
Before Width: | Height: | Size: 522 B |
Binary file not shown.
|
Before Width: | Height: | Size: 773 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1,5 +1,5 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal" android:viewportHeight="24"
|
||||
android:tint="@android:color/white" android:viewportHeight="24"
|
||||
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#000" android:pathData="M20,15.5C18.8,15.5 17.5,15.3 16.4,14.9C16.3,14.9 16.2,14.9 16.1,14.9C15.8,14.9 15.6,15 15.4,15.2L13.2,17.4C10.4,15.9 8,13.6 6.6,10.8L8.8,8.6C9.1,8.3 9.2,7.9 9,7.6C8.7,6.5 8.5,5.2 8.5,4C8.5,3.5 8,3 7.5,3H4C3.5,3 3,3.5 3,4C3,13.4 10.6,21 20,21C20.5,21 21,20.5 21,20V16.5C21,16 20.5,15.5 20,15.5M5,5H6.5C6.6,5.9 6.8,6.8 7,7.6L5.8,8.8C5.4,7.6 5.1,6.3 5,5M19,19C17.7,18.9 16.4,18.6 15.2,18.2L16.4,17C17.2,17.2 18.1,17.4 19,17.4V19Z"/>
|
||||
<path android:fillColor="#000000" android:pathData="M20,15.5C18.8,15.5 17.5,15.3 16.4,14.9C16.3,14.9 16.2,14.9 16.1,14.9C15.8,14.9 15.6,15 15.4,15.2L13.2,17.4C10.4,15.9 8,13.6 6.6,10.8L8.8,8.6C9.1,8.3 9.2,7.9 9,7.6C8.7,6.5 8.5,5.2 8.5,4C8.5,3.5 8,3 7.5,3H4C3.5,3 3,3.5 3,4C3,13.4 10.6,21 20,21C20.5,21 21,20.5 21,20V16.5C21,16 20.5,15.5 20,15.5M5,5H6.5C6.6,5.9 6.8,6.8 7,7.6L5.8,8.8C5.4,7.6 5.1,6.3 5,5M19,19C17.7,18.9 16.4,18.6 15.2,18.2L16.4,17C17.2,17.2 18.1,17.4 19,17.4V19Z"/>
|
||||
</vector>
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
<vector android:autoMirrored="true" android:height="48dp"
|
||||
android:tint="?attr/colorControlNormal" android:viewportHeight="24"
|
||||
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M17.5,4.5c-1.95,0 -4.05,0.4 -5.5,1.5c-1.45,-1.1 -3.55,-1.5 -5.5,-1.5S2.45,4.9 1,6v14.65c0,0.65 0.73,0.45 0.75,0.45C3.1,20.45 5.05,20 6.5,20c1.95,0 4.05,0.4 5.5,1.5c1.35,-0.85 3.8,-1.5 5.5,-1.5c1.65,0 3.35,0.3 4.75,1.05C22.66,21.26 23,20.86 23,20.6V6C21.51,4.88 19.37,4.5 17.5,4.5zM21,18.5c-1.1,-0.35 -2.3,-0.5 -3.5,-0.5c-1.7,0 -4.15,0.65 -5.5,1.5V8c1.35,-0.85 3.8,-1.5 5.5,-1.5c1.2,0 2.4,0.15 3.5,0.5V18.5z"/>
|
||||
</vector>
|
||||
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/AndroidContactsView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
|
||||
@ -221,16 +221,6 @@
|
||||
android:text="@string/audio_settings" >
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/AndroidSettings"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/android_settings"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp">
|
||||
</TextView>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/aorSpinner"
|
||||
android:layout_marginTop="31dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<TextView
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/swapContactsIcon"
|
||||
android:id="@+id/swapIcon"
|
||||
android:title=""
|
||||
app:showAsAction="always"
|
||||
android:icon="@drawable/swap_contacts" />
|
||||
android:icon="@drawable/ic_test_swap" />
|
||||
|
||||
</menu>
|
||||
|
||||
@ -520,7 +520,7 @@
|
||||
Tallennustila-käyttöoikeutta.</string>
|
||||
<string name="no_restore">Et voi palauttaa sovelluksen tietoja ilman
|
||||
Tallennustila-käyttöoikeutta.</string>
|
||||
<string name="no_android_contacts">Et voi lisätä tai poistaa Android-yhteystietoja ilman
|
||||
<string name="no_android_contacts">Et voi käsitellä Androidin yhteystietoja ilman
|
||||
Kontaktit-käyttöoikeutta.</string>
|
||||
<string name="no_cameras">Sinulla ei ole yhtään tuettua video-kameraa.</string>
|
||||
<string name="show_password">Näytä salasana</string>
|
||||
|
||||
@ -475,7 +475,7 @@
|
||||
<string name="no_video_calls">Grant \"Camera\" permission to make or answer video calls.</string>
|
||||
<string name="no_backup">You are not able create backup without \"Storage\" permission.</string>
|
||||
<string name="no_restore">You are not able restore backup without \"Storage\" permission.</string>
|
||||
<string name="no_android_contacts">You are not able add or remove Android contacts without
|
||||
<string name="no_android_contacts">You are not able to access Android contacts without
|
||||
\"Contacts\" permission.</string>
|
||||
<string name="no_cameras">You don\'t have any supported video cameras.</string>
|
||||
<string name="show_password">Show Password</string>
|
||||
|
||||
Reference in New Issue
Block a user