Listing 15.11 - Simpler Solution for Depreciated startActivityForResult()

jpaone gave a great solution to the depreciated Fragment::startActivityForResult() in this chapter.

His solution works great, and he provided a lot of explanation as to what is going on, but it can be a lot simpler with a PickContact default contract. There are a lot of default contracts for other uses. You can find more default contracts here. And I’ve used another of the default contracts in the next chapter to help take a photo, described here.

Don’t bother creating the variables pickContactContract, pickContactCallback or pickContactLauncher.

Instead in the CrimeFragment::onStart function set up the suspect button click listener to use an ActivityResultLauncher named pickContact like this:

   override fun onStart() {
        super.onStart()
        ......
 
        suspectButton.apply {
            setOnClickListener {
                pickContact.launch(null)
            }
        }
    }

    val pickContact = registerForActivityResult(ActivityResultContracts.PickContact()) { contactUri ->
            val queryFields = arrayOf(ContactsContract.Contacts.DISPLAY_NAME)
            val cursor = contactUri?.let {
                requireActivity().contentResolver.query (it, queryFields, null, null, null)
            }
            cursor?.use {
                // Verify cursor contains at least one result
                if (it.count > 0) {
                    // Pull out first column of the first row of data, that's our suspect name
                    it.moveToFirst()
                    val suspect = it.getString(0)
                    crime.suspect = suspect
                    crimeDetailViewModel.saveCrime(crime)
                    suspectButton.text = suspect
                }
            }
    }

This works for me. Nice simple solution. Thanks Gazza.