The button is always disabled if I put checking before setting the onClickListener. Doesn’t matter if I use queryIntentActivity, resolveActiviy or just use intent.resolveActivity they all return null or empty content back. The strange thing is startActivity works fine that Contacts App launched and I could select a contact and query its display name without any problem. Can anyone give me a hand? Thanks.
btnSelectSuspect.apply {
val pickIntent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
val packageManager = requireActivity().packageManager
val resolverInfo = packageManager.queryIntentActivities(pickIntent, PackageManager.MATCH_DEFAULT_ONLY)
if (resolverInfo == null || resolverInfo.size == 0)
this.isEnabled = false;
else
setOnClickListener {
startActivityForResult(pickIntent, REQUEST_CONTACT)
}
}
The resolveActivity() method is very important and API dependent. If we are targeting API 29 (Android 10) or lower, then we can view what other apps exist on the device. Starting with API 30 (Android 11) and newer, the principle of least privilege applies and we need to tell the system what other packages to make visible to our app.
Here is the documentation page describing Package Visibility beginning in Android 11.
We must request permission to access anything outside of our app. Any interaction between our app and the OS goes in to the Manifest to register. In the AndroidManifest.xml, we need to tell the OS that we plan to query the Contacts package in order to pick a contact. The Contacts app should be part of the list of apps that automatically visible to our app.
But as soon as we add the data field to the intent, we now need to make an explicit query request. I was able to gain proper access using the following query in the manifest:
But no combination of attributes gave proper access. Only by using the package query did the intent with the data URI resolve. I feel there should be an alternate way, but I haven’t found it yet.
I agree the documentation is a bit confusing it seems to indicate any of the two alternatives (i.e. explicit package declaration or intent filters) would work.
This makes absolutely no sense to me because that isn’t the action name I can see in the debugger for the constructed Intent that gets passed to the package manager query. But it does seem to work so ¯\_(ツ)_/¯