以编程方式正确打开“设置”中的“关于设备”页面?

Pan*_*eet 7 java android android-intent

startActivity(new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS)); 在三星设备中打开此页面:

在此处输入图片说明

但是,我希望它像其他 Android 设备一样打开此页面,我该怎么做?

在此处输入图片说明

ami*_*phy 2

重点是这似乎是不可能的。我们来看看是什么原因。

可以DeviceInfoSettingsActivity通过意图调用打开,例如:

Intent intent = new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

或者

Intent intent = new Intent();
intent.setClassName(
    "com.android.settings",
    "com.android.settings.Settings$DeviceInfoSettingsActivity"
);
startActivity(intent)
Run Code Online (Sandbox Code Playgroud)

正如你在这里看到的:

https://android.googlesource.com/platform/packages/apps/Settings/+/master/src/com/android/settings/Settings.java

Settings它的所有内部类都是 的子类SettingsActivity。通过查看 的源代码SettingsActivity,我们发现可以显示子设置,将片段名称作为意图额外的键传递":settings:show_fragment"SettingsActivity

SettingsActivity#onCreate()然后SettingsActivity#launchSettingFragment()

如果我们深入研究显示目标屏幕的日志,我们会看到目标片段名称是com.samsung.android.settings.deviceinfo.SoftwareInfoSettings

但问题是,对片段名称进行了检查,SettingsActivity#isValidFragment()允许特定片段导航到,它们是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;
}
Run Code Online (Sandbox Code Playgroud)

在设置中显示其他片段的替代方法是打开SubSettings活动,该活动会覆盖isValidFragment接受每个片段。

@Override
protected boolean isValidFragment(String fragmentName) {
    Log.d("SubSettings", "Launching fragment " + fragmentName);
    return true;
}
Run Code Online (Sandbox Code Playgroud)

这正是SoftwareInfoSettings显示时发生的情况:

D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
Run Code Online (Sandbox Code Playgroud)

不幸的是,启动SubSettings除了uid启动器的 uid 之外是不可能的,因为它不是从外部可见的导出活动:

AndroidManifest.xml

<activity android:name=".SubSettings"
    android:parentActivityName="Settings"
    android:theme="@style/Theme.SubSettings"/>
Run Code Online (Sandbox Code Playgroud)

如果您尝试运行:

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);
Run Code Online (Sandbox Code Playgroud)

会看到这个错误日志:

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
Run Code Online (Sandbox Code Playgroud)

不幸的是,由于isValidFragment()SettingsGateway#ENTRY_FRAGMENTS是平台的一部分,而不是应用程序的运行时,因此即使使用反射也无法更改它们。