Hi guys,
I want to share with you my proposed solution to this challenge, here is the steps:
1- create the UI elements
2- create a new field in Crime class: phone field where i’ll save the phone number of suspect
@Entity
data class Crime(
@PrimaryKey val id: UUID = UUID.randomUUID(),
var title: String = “”,
var date: Date = Date(),
var isSolved: Boolean = false,
var suspect: String = “”,
var phone: String = “”)
3- In CrimeDatabase, i modified its version and added a new Migration object to it
@Database(entities = [Crime::class], version = 3)
@TypeConverters(CrimeTypeConverters::class)
abstract class CrimeDatabase : RoomDatabase() {
abstract fun crimeDao(): CrimeDao
}
val migration_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(“ALTER TABLE Crime ADD COLUMN phone TEXT NOT NULL DEFAULT ‘’”)
}
4- To apply this migration, i added it in the crimeRepository when creating the database
class CrimeRepository private constructor(context: Context){
private val database: CrimeDatabase= Room.databaseBuilder( context.applicationContext, CrimeDatabase::class.java, DATABASE_NAME
).addMigrations(migration_2_3)
.build()
After finishing with the model layer, i will change the CrimeFragment,
5- i create the callSuspectButton object, then i get its reference in onCreateView
callSuspectButton = view.findViewById(R.id.call_suspect) as Button
6- To get the suspect phone number , i modified the overrided function onActivityResult (Here is the central part of this challenge):
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when { resultCode != Activity.RESULT_OK -> return requestCode == REQUEST_CONTACT && data != null -> { val contactUri: Uri? = data.data // queryFieldsName: a List to return the DISPLAY_NAME Column Only queryFieldsName = arrayOf(ContactsContract.Contacts.DISPLAY_NAME) // queryFieldsId: a List to return the _ID Column Only, i will use it to get the suspect Id val queryFieldsId = arrayOf(ContactsContract.Contacts._ID) val cursorName = requireActivity().contentResolver .query(contactUri!!, queryFieldsName, null, null, null) cursorName?.use { if (it.count == 0) { return } it.moveToFirst() val suspect = it.getString(0) crime.suspect = suspect suspectButton.text = suspect } // I created another Cursor to get the suspect Id val cursorId = requireActivity().contentResolver .query(contactUri!!, queryFieldsId, null, null, null) cursorId?.use { if (it.count == 0) { return } it.moveToFirst() // here i put the suspect Id in contactId to use it later (to get the phone number) val contactId = it.getString(0) // This is the Uri to get a Phone number val phoneURI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI // phoneNumberQueryFields: a List to return the PhoneNumber Column Only val phoneNumberQueryFields = arrayOf(ContactsContract.CommonDataKinds.Phone.NUMBER) // phoneWhereClause: A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself) val phoneWhereClause = "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?" // This val replace the question mark in the phoneWhereClause val val phoneQueryParameters = arrayOf(contactId) val phoneCursor = requireActivity().contentResolver .query(phoneURI, phoneNumberQueryFields, phoneWhereClause, phoneQueryParameters, null ) phoneCursor?.use { cursorPhone -> cursorPhone.moveToFirst() val phoneNumValue = cursorPhone.getString(0) // after retrieving the phone number i put it in the crime.phone crime.phone = phoneNumValue } crimeDetailViewModel.saveCrime(crime) } } } }
7- in onStart() function, i implementd an onClickListener on callSuspectButton
callSuspectButton.setOnClickListener { val callContactIntent = Intent(Intent.ACTION_DIAL).apply { val phone = crime.phone data = Uri.parse("tel:$phone") } // this intent will call the phone number given in Uri.parse("tel:$phone") startActivity(callContactIntent) }
I hope this solution help you in your challenge