【问题标题】:Programmatically open 'About device' page in Settings correctly?以编程方式正确打开“设置”中的“关于设备”页面?
【发布时间】:2020-06-12 12:00:52
【问题描述】:

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

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

【问题讨论】:

    标签: java android android-intent


    【解决方案1】:

    正如佩德罗·安东尼奥所说:

    如果它不适用于 SAMSUNG 设备,恐怕它可能是不可能的。至少没有官方答案。很多时候供应商修改了库存的Android,因此三星设备的设置应用程序与库存的AOSP不同,官方方法不起作用。

    当我们打电话时:

    Intent i = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
    startActivity(i);
    

    我们指的是活动 com.android.settings.Settings$DeviceInfoSettingsActivity,在日志中我们可以看到活动已启动

    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
    

    在华为 P10 等设备上,软件信息数据是 DeviceInfoSettingsActivity 的一部分。经过一番挖掘,我发现三星 S7 设备上的软件信息是在 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
    

    我不确定是否可以访问 DeviceInfoSettingsActivity 代码(我不能)并查看是否可以发送一些额外的数据来打开特定的 Fragment。因此,在这一点上,我认为不可能从意图启动该特定片段。

    【讨论】:

      【解决方案2】:

      主要的一点是它似乎不可能。让我们看看是什么原因。

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

      Intent intent = new Intent(android.provider.Settings.ACTION_DEVICE_INFO_SETTINGS);
      startActivity(intent);
      

      Intent intent = new Intent();
      intent.setClassName(
          "com.android.settings",
          "com.android.settings.Settings$DeviceInfoSettingsActivity"
      );
      startActivity(intent)
      

      如您所见:

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

      Settings 及其所有内部类都是SettingsActivity 的子类。通过查看SettingsActivity 的源代码,我们发现可以显示子设置,将片段名称作为intent extra 以":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;
      }
      

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

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

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

      D/Settings: packageName : com.android.settings className : com.android.settings.SubSettings
      D/SubSettings: Launching fragment com.samsung.android.settings.deviceinfo.SoftwareInfoSettings
      

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

      AndroidManifest.xml:

      <activity android:name=".SubSettings"
          android:parentActivityName="Settings"
          android:theme="@style/Theme.SubSettings"/>
      

      如果你尝试运行:

      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);
      

      会看到这个错误日志:

      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
      

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

      【讨论】:

        【解决方案3】:

        正如 android 文档所说,您应该使用

        Intent i = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
        startActivity(i);
        

        https://developer.android.com/reference/android/provider/Settings#ACTION_DEVICE_INFO_SETTINGS

        如果它不适用于 SAMSUNG 设备,恐怕它可能是不可能的。至少没有官方答案。很多时候供应商修改了库存的Android,因此三星设备的设置应用程序与库存的AOSP不同,官方方法不起作用。

        【讨论】:

          猜你喜欢
          • 2021-07-12
          • 2016-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-27
          • 2013-02-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多