Challenge: Another Implicit Intent - Solution

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