APPLICATION_PREFERENCES and Security
Android N lets you link an activity of yours into your app’s page in
Settings. Just add an <intent-filter>
:
<activity
android:name="EditPreferences"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Android N’s Settings app will look for the activity in your app that
has that <intent-filter>
. If Settings finds one, it will add a gear
icon to your app’s page in Settings, and if the user taps the gear, they
will be taken to your designated activity. The idea is that you would
use this for your own application settings, so the user can navigate
from Settings to your app’s settings, if desired.
At the risk of quoting a meme, this is nice.
However, most likely, your settings activity did not have an
<intent-filter>
prior to adding this one. By adding this <intent-filter>
,
you have made this activity be exported. Any app can start your activity
whenever the app wants. Your activity needs to be exported, so that
the Settings app can start the activity.
However, there is a substantial difference between “the Settings app can start the activity” and “any app can start the activity”. If your settings are fairly banal, there may be no issue. But if your settings includes things like account information, you might want to limit what apps can start it.
One way to constrain this is to add android:permission
to the
<activity>
, indicating that only apps that hold a certain permission
can start the activity. If we pick a good permission, Settings will
hold it, but other apps will not. Unfortunately,
there is no documentation for what permssion we should use.
WRITE_SECURE_SETTINGS
seems like a likely candidate, though. Clearly,
the Settings app will hold it. And, since only system apps can hold
that permission, the run-of-the-mill apps that the user installs will
not be able to start your activity.
That gives us:
<activity
android:name="EditPreferences"
android:label="@string/app_name"
android:permission="android.permission.WRITE_SECURE_SETTINGS">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
With luck, we will get official advice on this someday.
UPDATE 2016-08-18: cketti points out that
you can use android:exported="false"
to block other apps,
yet Settings can still start the activity.
Right now,
I am not quite certain why this works,
but it does.