Programmatically open 'About device' page in Settings correctly?
As Pedro Antonio said:
If it doesn't work for SAMSUNG devices I'm afraid it will probably not be possible. At least with no official answer. Many times vendors modify stock Android so for SAMSUNG devices settings app is different than stock AOSP, and the official method will not work.
When we call:
Intent i = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(i);
we are referring to activity com.android.settings.Settings$DeviceInfoSettingsActivity and in logs we can see that activity is started
2020-06-26 11:33:43.804 4838-5126/? I/ActivityManager: START u0 {act=null typ=null flg=0x8000 cmp=ComponentInfo{com.android.settings/com.android.settings.Settings$DeviceInfoSettingsActivity}} from uid 1000
On devices like Huawei P10, Software Information data is part of DeviceInfoSettingsActivity. After some digging i found out that on Samsung S7 device Software Information is Fragment that is called inside DeviceInfoSettingsActivity
2020-06-26 11:44:25.780 7103-9703/? D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
2020-06-26 11:44:25.812 7103-7103/? D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
I am not sure is it possible to access DeviceInfoSettingsActivity code (I couldn't) and see if you can send some extra data to open specific Fragment. So at this point i do not believe that it is possible to launch that specific fragment from intent.
As the android documentation says, you should use
Intent i = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(i);
https://developer.android.com/reference/android/provider/Settings#ACTION_DEVICE_INFO_SETTINGS
If it doesn't work for SAMSUNG devices I'm afraid it will probably not be possible. At least with no official answer. Many times vendors modify stock Android so for SAMSUNG devices settings app is different than stock AOSP, and the official method will not work.
The main point is it seems impossible. Let's look at what is the reason.
The DeviceInfoSettingsActivity
can be opened by an intent call like:
Intent intent = new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(intent);
or
Intent intent = new Intent();
intent.setClassName(
"com.android.settings",
"com.android.settings.Settings$DeviceInfoSettingsActivity"
);
startActivity(intent)
As you can see here:
https://android.googlesource.com/platform/packages/apps/Settings/+/master/src/com/android/settings/Settings.java
Settings
and all of its inner classes are children of SettingsActivity
. By taking a look at source code of SettingsActivity
, we found out it is possible to show a sub-settings, passing the fragment name as an intent extra with key ":settings:show_fragment"
to the SettingsActivity
:
SettingsActivity#onCreate()
then SettingsActivity#launchSettingFragment()
If we dig into logs where the target screen is shown, we'd see that the target fragment name is com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
.
But the problem is that there is a check on fragment names at SettingsActivity#isValidFragment()
which allows specific fragments to navigate to and they are SettingsGateway#ENTRY_FRAGMENTS
:
protected boolean isValidFragment(String fragmentName) {
// Almost all fragments are wrapped in this,
// except for a few that have their own activities.
for (int i = 0; i < SettingsGateway.ENTRY_FRAGMENTS.length; i++) {
if (SettingsGateway.ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
}
return false;
}
The alternative for showing other fragments in settings is to open SubSettings
activity which overrides the isValidFragment
to accepts every fragment.
@Override
protected boolean isValidFragment(String fragmentName) {
Log.d("SubSettings", "Launching fragment " + fragmentName);
return true;
}
That is exactly what happens when the SoftwareInfoSettings
is shown:
D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
Unfortunately, starting the SubSettings
from uid
except launcher's uid isn't possible, because it is not an exported activity to be visible from the outside:
AndroidManifest.xml:
<activity android:name=".SubSettings"
android:parentActivityName="Settings"
android:theme="@style/Theme.SubSettings"/>
If you try to run:
Intent intent = new Intent();
intent.setClassName(
"com.android.settings",
"com.android.settings.SubSettings"
);
intent.putExtra(
":settings:show_fragment",
"com.samsung.android.settings.deviceinfo.SoftwareInfoSettings"
);
startActivity(intent);
will see this error log:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.aminography.settingsapp, PID: 14566
java.lang.SecurityException: Permission Denial:
starting Intent { flg=0x10000000 cmp=com.android.settings/.SubSettings (has extras) }
from ProcessRecord{fac1d09 14566:com.aminography.settingsapp/u0a104} (pid=14566, uid=10104)
not exported from uid 1000
Unfortunately, since isValidFragment()
and SettingsGateway#ENTRY_FRAGMENTS
are parts of the platform, not your application's runtime, it's impossible to change them even with reflection.