Chapter 15 Implicit Intents
Contacts permissions
How are you getting permission to read from the contacts database? The contacts app is extending
its permissions to you. The contacts app has full permissions to the contacts database. When
the contacts app returns a data URI in an Intent to the parent activity, it also adds the flag
Intent.FLAG_GRANT_READ_URI_PERMISSION. This flag signals to Android that the parent activity in
CriminalIntent should be allowed to use this data one time. This works well because you do not really
need access to the entire contacts database. You only need access to one contact inside that database.
Checking for responding activities
The first implicit intent you created in this chapter will always be responded to in some way – there
may be no way to send a report, but the chooser will still display properly. However, that is not the case
for the second example: Some devices or users may not have a contacts app, and if the OS cannot find
a matching activity, then the app will crash.
The fix is to check with part of the OS called the PackageManager first. Do this in onCreateView(...).
Listing 15.14 Guarding against no contacts app (CrimeFragment.java)
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
if (mCrime.getSuspect() != null) {
mSuspectButton.setText(mCrime.getSuspect());
}
PackageManager packageManager = getActivity().getPackageManager();
if (packageManager.resolveActivity(pickContact,
PackageManager.MATCH_DEFAULT_ONLY) == null) {
mSuspectButton.setEnabled(false);
}
return v;
}
PackageManager knows about all the components installed on your Android device, including
all of its activities. (You will run into the other components later on in this book.) By calling
resolveActivity(Intent, int), you ask it to find an activity that matches the Intent you gave it.
The MATCH_DEFAULT_ONLY flag restricts this search to activities with the CATEGORY_DEFAULT flag, just
like startActivity(Intent) does.
If this search is successful, it will return an instance of ResolveInfo telling you all about which
activity it found. On the other hand, if the search returns null, the game is up – no contacts app. So
you disable the useless suspect button.
If you would like to verify that your filter works, but do not have a device without a contacts
application, temporarily add an additional category to your intent. This category does nothing, but it
will prevent any contacts applications from matching your intent.