APPLICATION_PREFERENCES and Security
Android N lets you link an activity of yours into your app’s page in
Settings. Just add an
<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
<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
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.
I am not quite certain why this works,
but it does.
Stuck on an Android problem? Subscribers have access to live office hours chats with Mark Murphy, to help you work through your challenges!