How I Isolated the Adobe Reader Activity Issue
Earlier today, somebody posted a question on StackOverflow
regarding a SecurityException
when trying to send a PDF to
Adobe Reader via ACTION_SEND
. I thought it might be useful to write
up how I went about determining the nature of the problem.
The question author took care of my first guess for me, by indicating
that the ACTION_SEND
code worked fine with other PDF apps. That
eliminated any issue regarding read permissions on wherever the PDF
was stored (not mentioned in the question).
Fortunately, I have two apps installed on my Galaxy Nexus relevant to this issue. One is Adobe Reader, as you might expect. The other is AppXplore, published by Sony (or Sony Ericsson, as their app description still lists them).
AppXplore is a very handy app for inspecting the manifest of another
application installed on your device. Simply running AppXplore and
tapping on an app brings up general information about the app itself.
Then, choosing a “Show manifest file” options menu item brings up
a scrollable TextView
of the contents of the manifest… more or less.
It is actually “a regenerated verison of AndroidManifest.xml from
application’s binary package and may not match exactly with the
original AndroidManifest.xml file”.
However, it is certainly ample for problems like this. And, there are no pesky software piracy issues typically involved in getting one’s hands on an APK file for an app on the Play Store.
The SO question helpfully listed the activity that was failing:
ARSendForSignature
. Scrolling down in the generated manifest for
Adobe Reader shows that ARSendForSignature
indeed has an
<intent-filter>
for ACTION_SEND
. However, it also has
android:exported="false"
.
The default exported state for Android components is:
- Components with an
<intent-filter>
are exported and can be launched by other applications - A
ContentProvider
is exported by default, despite having no<intent-filter>
- Everything else is not exported by default and therefore cannot be launched by other applications
The android:exported
attribute on an <activity>
allows you to override
those defaults.
So, what happens?
The user does something in the original activity that triggers
a startActivity()
with an ACTION_SEND
Intent
for the
application/pdf
MIME type. The chooser lists all activities that
have an <intent-filter>
matching that specification. When the user
taps on the chooser item for Adobe Reader, the chooser crashes,
because it cannot start up Adobe Reader’s ACTION_SEND
activity,
because it is marked as not exported.
The real problem here is the chooser. The chooser should be filtering
out anything that is not exported and is not from its own application,
no matter what the <intent-filter>
may have. That’s why I went ahead,
reproduced the problem with my own code, and
filed an issue.
Tactically, though, Adobe should either mark this activity as being
exported (so ACTION_SEND
works) or remove the <intent-filter>
(thereby having it not appear in choosers for ACTION_SEND
).