Commit 59d0e3ae authored by wanglei's avatar wanglei

...获取数据

parent 17d4a4fa
......@@ -24,7 +24,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:name=".MyApplication"
......@@ -37,6 +37,12 @@
android:supportsRtl="true"
android:theme="@style/Theme.ScanQR"
tools:targetApi="31">
<activity
android:name=".ui.contact.ContractCodeActivity"
android:exported="false" />
<activity
android:name=".ui.contact.ContractActivity"
android:exported="false" />
<activity
android:name=".ui.telephone.TelephoneCodeActivity"
android:exported="false"
......
......@@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
......@@ -41,6 +42,7 @@ abstract class BaseActivity<VB : ViewBinding>(
var onCreateI = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
configSystemBar()
onCreateI++
LogEx.logDebug(TAG, "lifecycle $tagNo onCreate ${javaClass.simpleName} $onCreateI")
......
package com.base.scanqr.bean
import com.base.scanqr.utils.QRCodeUtils.getPairKeyValue
//MECARD:
// N:王雷;
// TEL:17608923756;
// EMAIL:179621228@qq.com;
// ADR:成都;
data class ContractUIBean(
var n: String = "",
var tel: String = "",
var email: String = "",
var adr: String = ""
) : ScanBean(FunctionUIBean.KEY_CONTACT) {
companion object {
fun isContractQR(qrCodeValue: String): Boolean {
if (qrCodeValue.startsWith("MECARD:")) {
return true
}
return false
}
fun createContractQrString(bean: ContractUIBean): String {
val qrContent = StringBuilder()
qrContent.append("MECARD:")
qrContent.append("N:").append(bean.n).append("")
qrContent.append("TEL:").append(bean.tel).append("")
qrContent.append("EMAIL:").append(bean.email).append("")
qrContent.append("ADR:").append(bean.adr).append("")
return qrContent.toString()
}
fun createContractBean(qrCodeValue: String): ContractUIBean {
val contractUIBean = ContractUIBean()
val start = "MECARD:"
val sub = qrCodeValue.subSequence(start.length, qrCodeValue.length)
val list = sub.split(";")
list.forEach {
val kv = getPairKeyValue(it)
if (kv.first == "N") {
contractUIBean.n = kv.second
}
if (kv.first == "TEL") {
contractUIBean.tel = kv.second
}
if (kv.first == "EMAIL") {
contractUIBean.email = kv.second
}
if (kv.first == "ADR") {
contractUIBean.adr = kv.second
}
}
return contractUIBean
}
}
}
package com.base.scanqr.bean
data class MMediaContract(
var name: String = "",
var addressList: List<String> = listOf(),
var phoneList: List<String> = listOf(),
var emailList: List<String> = listOf()
)
package com.base.scanqr.ui.contact
import android.Manifest
import android.content.Intent
import android.net.Uri
import androidx.activity.addCallback
import androidx.core.view.updatePadding
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import com.base.scanqr.R
import com.base.scanqr.ads.AdsMgr
import com.base.scanqr.ads.AdsShowCallBack
import com.base.scanqr.base.BaseActivity
import com.base.scanqr.bean.ContractUIBean
import com.base.scanqr.databinding.ActivityContractBinding
import com.base.scanqr.utils.BarUtils
import com.base.scanqr.utils.ContactUtils.queryMediaContract
import com.base.scanqr.utils.IntentUtils.intentPickContacts
import com.base.scanqr.utils.LogEx
import com.base.scanqr.utils.PermissionUtils.checkContactsReadPermission
import com.base.scanqr.utils.ToastUtils.toast
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class ContractActivity : BaseActivity<ActivityContractBinding>(ActivityContractBinding::inflate) {
private val contractUIBean = ContractUIBean()
override fun onResumeOneShoot() {
super.onResumeOneShoot()
val flag = changeLanguage()
if (flag) return
}
override fun initView() {
super.initView()
binding.clTop.updatePadding(top = BarUtils.getStatusBarHeight())
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_item)
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
AdsMgr.showInsert(this@ContractActivity, false, object : AdsShowCallBack() {
override fun close(where: Int) {
finishToMainTop()
}
override fun failed(where: Int) {
finishToMainTop()
}
override fun googleFailed(where: Int) {
finishToMainTop()
}
})
}
binding.flBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.editFullName.addTextChangedListener { s ->
contractUIBean.n = s.toString()
}
binding.editAddress.addTextChangedListener { s ->
contractUIBean.adr = s.toString()
}
binding.editPhone.addTextChangedListener { s ->
contractUIBean.tel = s.toString()
}
binding.editEmail.addTextChangedListener { s ->
contractUIBean.email = s.toString()
}
binding.tvSelect.setOnClickListener {
if (!checkContactsReadPermission()) {
launcher.launch(arrayOf(Manifest.permission.READ_CONTACTS)) {
if (checkContactsReadPermission()) {
pickContract()
}
}
} else {
pickContract()
}
}
binding.flQueren.setOnClickListener {
if (contractUIBean.n.isEmpty()) {
toast("Enter invalidate full name contact", true)
return@setOnClickListener
}
if (contractUIBean.adr.isEmpty()) {
toast("Enter invalidate address", true)
return@setOnClickListener
}
if (contractUIBean.tel.isEmpty()) {
toast("Enter invalidate telephone number", true)
return@setOnClickListener
}
if (contractUIBean.email.isEmpty()) {
toast("Enter invalidate email", true)
return@setOnClickListener
}
startActivity(Intent(this, ContractCodeActivity::class.java).apply {
putExtra("data", Gson().toJson(contractUIBean))
})
finish()
}
}
private fun pickContract() {
val intent = intentPickContacts()
launcher.launch(intent) { result ->
val contactUri: Uri? = result.data?.data
LogEx.logDebug(TAG, "contactUri=$contactUri")
if (contactUri != null) {
lifecycleScope.launch(Dispatchers.IO) {
val media = queryMediaContract(contactUri)
LogEx.logDebug(TAG, "media=$media")
if (media != null) {
contractUIBean.n = media.name
if (media.phoneList.isNotEmpty()) {
contractUIBean.tel = media.phoneList.first()
}
if (media.emailList.isNotEmpty()) {
contractUIBean.email = media.emailList.first()
}
if (media.addressList.isNotEmpty()) {
contractUIBean.adr = media.addressList.first()
}
}
launch(Dispatchers.Main) {
binding.editFullName.setText(contractUIBean.n)
binding.editAddress.setText(contractUIBean.adr)
binding.editPhone.setText(contractUIBean.tel)
binding.editEmail.setText(contractUIBean.email)
}
}
}
}
}
}
\ No newline at end of file
package com.base.scanqr.ui.contact
import com.base.scanqr.base.BaseActivity
import com.base.scanqr.databinding.ActivityContractBinding
class ContractCodeActivity : BaseActivity<ActivityContractBinding>(ActivityContractBinding::inflate) {
override fun initView() {
super.initView()
}
override fun initListener() {
super.initListener()
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@ import com.base.scanqr.ads.AdsMgr
import com.base.scanqr.ads.AdsShowCallBack
import com.base.scanqr.base.BaseFragment
import com.base.scanqr.bean.FunctionUIBean
import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_CONTACT
import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_EMAIL
import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_EVENT
import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_TELEPHONE
......@@ -15,6 +16,7 @@ import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_TEXT
import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_WEBSITE
import com.base.scanqr.bean.FunctionUIBean.Companion.KEY_WIFI
import com.base.scanqr.databinding.FragmentCreateBinding
import com.base.scanqr.ui.contact.ContractActivity
import com.base.scanqr.ui.email.EmailActivity
import com.base.scanqr.ui.event.EventActivity
import com.base.scanqr.ui.telephone.TelephoneActivity
......@@ -42,7 +44,7 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
FunctionUIBean(KEY_EMAIL, R.mipmap.h_email, resources.getString(R.string.email)),
FunctionUIBean(KEY_WEBSITE, R.mipmap.h_website, resources.getString(R.string.website)),
FunctionUIBean(KEY_EVENT, R.mipmap.h_event, resources.getString(R.string.event)),
// FunctionUIBean(KEY_CONTACT, R.mipmap.h_contact, resources.getString(R.string.contact)),
FunctionUIBean(KEY_CONTACT, R.mipmap.h_contact, resources.getString(R.string.contact)),
// FunctionUIBean(KEY_LOCATION, R.mipmap.h_loction, resources.getString(R.string.location)),
FunctionUIBean(KEY_TELEPHONE, R.mipmap.h_telephone, resources.getString(R.string.telephone)),
// FunctionUIBean(KEY_MESSAGE, R.mipmap.h_message, resources.getString(R.string.message)),
......@@ -94,6 +96,10 @@ class CreateFragment : BaseFragment<FragmentCreateBinding>(FragmentCreateBinding
KEY_TELEPHONE -> {
startActivity(Intent(requireContext(), TelephoneActivity::class.java))
}
KEY_CONTACT -> {
startActivity(Intent(requireContext(), ContractActivity::class.java))
}
}
}
......
......@@ -19,6 +19,7 @@ import com.base.scanqr.bean.NotificationSendBean.Companion.ACTION_ID_WIFI
import com.base.scanqr.databinding.ActivityStartBinding
import com.base.scanqr.fcm.notification.NotificationHoverUtils
import com.base.scanqr.service.StayJobService.Companion.startJob
import com.base.scanqr.ui.contact.ContractActivity
import com.base.scanqr.ui.email.EmailActivity
import com.base.scanqr.ui.event.EventActivity
import com.base.scanqr.ui.language.LanguageActivity
......@@ -45,6 +46,10 @@ class StartActivity : BaseActivity<ActivityStartBinding>(ActivityStartBinding::i
override fun initView() {
super.initView()
startActivity(Intent(this, ContractActivity::class.java))
finish()
return
NotificationHoverUtils.stopNotificationHandler()
if (ConstObject.ifAgreePrivacy) {
......
......@@ -2,12 +2,17 @@ package com.base.scanqr.utils
import android.annotation.SuppressLint
import android.content.ContentUris
import android.content.ContentUris.withAppendedId
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.ContactsContract
import com.base.scanqr.bean.MMediaContract
object ContactUtils {
private val TAG = "ContactUtils"
@SuppressLint("Range")
fun Context.queryTel(contactUri: Uri): String? {
val cursor = contentResolver.query(
......@@ -21,7 +26,7 @@ object ContactUtils {
if (cursor.moveToFirst()) {
val phoneId = cursor.getLong(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID))
val phoneCursor = contentResolver.query(
ContentUris.withAppendedId(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, phoneId),
withAppendedId(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, phoneId),
null,
null,
null,
......@@ -39,4 +44,158 @@ object ContactUtils {
}
return null
}
fun Context.getContractId(lookupUri: Uri): String? {
val contactId = ContactsContract.Contacts.lookupContact(contentResolver, lookupUri)?.lastPathSegment
return contactId
}
@SuppressLint("Range")
fun Context.getLookupKey(lookupUri: Uri): String {
val cursor = contentResolver.query(lookupUri, arrayOf(ContactsContract.Contacts.LOOKUP_KEY), null, null, null)
cursor?.use {
if (it.moveToFirst()) {
return it.getString(it.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
}
}
return ""
}
@SuppressLint("Range")
fun Context.queryMediaContract(lookupUri: Uri): MMediaContract? {
val contractId = getContractId(lookupUri)
LogEx.logDebug(TAG, "contractId=$contractId")
val lookupKey = getLookupKey(lookupUri)
LogEx.logDebug(TAG, "lookupKey=$lookupKey")
val bean = MMediaContract()
if (contractId != null) {
// 构建查询Uri,使用联系人ID
val contactUri = withAppendedId(ContactsContract.Contacts.CONTENT_URI, contractId.toLong())
var cursor: Cursor? = null
try {
cursor = contentResolver.query(contactUri, null, null, null, null)
cursor?.use {
if (cursor.moveToFirst()) {
val name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY))
LogEx.logDebug(TAG, "name=$name")
bean.name = name
}
}
cursor?.close()
} catch (e: Exception) {
cursor?.close()
} finally {
cursor?.close()
}
val phones = queryPhones(contractId)
LogEx.logDebug(TAG, "phones=${phones.size}")
bean.phoneList = phones
val emails = queryContactEmails(contractId)
LogEx.logDebug(TAG, "emails=${emails.size}")
bean.emailList = emails
val addressList = queryContactAddressList(contractId)
LogEx.logDebug(TAG, "addressList=${addressList.size}")
bean.addressList = addressList
return bean
}
return null
}
private fun Context.queryPhones(contactId: String): List<String> {
val phones = ArrayList<String>()
val contactPhoneUri = withAppendedId(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, contactId.toLong())
var cursor: Cursor? = null
try {
// 使用提供的 contactUri 来查询电话号码
cursor = contentResolver.query(
contactPhoneUri,
arrayOf(ContactsContract.CommonDataKinds.Phone.NUMBER),
null,
null,
null
)
cursor?.use {
if (cursor.moveToFirst()) {
do {
val phone = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))
phones.add(phone)
} while (cursor.moveToNext()) // 使用 moveToNext() 而不是 moveToFirst()
}
}
cursor?.close()
} catch (e: Exception) {
// 异常处理
e.printStackTrace()
} finally {
cursor?.close() // 确保在 finally 块中关闭 cursor
}
return phones
}
@SuppressLint("Range")
fun Context.queryContactEmails(contactId: String): List<String> {
val emails = mutableListOf<String>()
val projection = arrayOf(
ContactsContract.CommonDataKinds.Email.CONTACT_ID,
ContactsContract.CommonDataKinds.Email.ADDRESS
)
val selection = "${ContactsContract.CommonDataKinds.Email.CONTACT_ID} = ?"
val cursor = contentResolver.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
projection, selection, arrayOf(contactId), null
)
if (cursor != null && cursor.moveToFirst()) {
do {
val email = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS))
// 处理获取到的联系人ID和邮件地址
// 例如,显示在UI上或者保存起来
emails.add(email)
} while (cursor.moveToNext())
cursor.close()
}
return emails
}
@SuppressLint("Range")
private fun Context.queryContactAddressList(contactId: String): List<String> {
val addressList = mutableListOf<String>()
val projection = arrayOf(
ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID,
ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS
)
val selection = "${ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID} = ?"
val cursor = contentResolver.query(
ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,
projection, selection, arrayOf(contactId), null
)
if (cursor != null) {
while (cursor.moveToNext()) {
val address =
cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS))
addressList.add(address)
}
cursor.close()
}
return addressList
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.event.EventActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/fanhui"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="@string/contact"
android:textColor="@color/black"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/fl_back"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/fl_queren"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/queren"
tools:ignore="ContentDescription" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:text="@string/name"
android:textColor="#6473F8"
android:textSize="16sp" />
<EditText
android:id="@+id/edit_full_name"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_f4f4f4_15"
android:hint="@string/enter_full_name"
android:paddingHorizontal="14dp"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="16sp"
tools:ignore="Autofill,LabelFor,TextFields" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:text="@string/address"
android:textColor="#6473F8"
android:textSize="16sp" />
<EditText
android:id="@+id/editAddress"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_f4f4f4_15"
android:hint="@string/enter_address"
android:paddingHorizontal="14dp"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="16sp"
tools:ignore="Autofill,LabelFor,TextFields" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:text="@string/phone"
android:textColor="#6473F8"
android:textSize="16sp" />
<EditText
android:id="@+id/editPhone"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_f4f4f4_15"
android:hint="@string/enter_telephone_number"
android:paddingHorizontal="14dp"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="16sp"
tools:ignore="Autofill,LabelFor,TextFields" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:text="@string/email"
android:textColor="#6473F8"
android:textSize="16sp" />
<EditText
android:id="@+id/editEmail"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_f4f4f4_15"
android:hint="@string/enter_email"
android:paddingHorizontal="14dp"
android:singleLine="true"
android:textColor="@color/black"
android:textSize="16sp"
tools:ignore="Autofill,LabelFor,TextFields" />
<TextView
android:id="@+id/tvSelect"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="18dp"
android:background="@drawable/bg_stroke_6473f8_90"
android:gravity="center"
android:text="@string/select_in_contacts"
android:textColor="#6473F8"
android:textSize="17sp" />
<com.base.scanqr.ads.NativeParentView
android:id="@+id/fl_ad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:background="@drawable/bg_ecf6ff_10"
android:minHeight="258dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent">
<io.supercharge.shimmerlayout.ShimmerLayout
android:id="@+id/shimmerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="16dp"
app:shimmer_angle="25"
app:shimmer_animation_duration="2000"
app:shimmer_auto_start="true"
app:shimmer_color="#33ffffff"
app:shimmer_mask_width="0.2">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/zhanweitu"
tools:ignore="ContentDescription,ImageContrastCheck" />
</io.supercharge.shimmerlayout.ShimmerLayout>
</com.base.scanqr.ads.NativeParentView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.contact.ContractCodeActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -129,5 +129,11 @@
</string>
<string name="phone_number">Phone number</string>
<string name="link_website">Link Website</string>
<string name="name">Name</string>
<string name="enter_full_name">Enter full name</string>
<string name="address">Address</string>
<string name="enter_address">Enter address</string>
<string name="enter_telephone_number">Enter telephone number</string>
<string name="enter_email">Enter email</string>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment