android10.0(Q) Settings 添加设置项————静态方式

前言

之前写过一篇6.0Settings配置项动态添加和静态添加,已经是很久以前了,

从8.1后Settings加载方式进行了较大改动,到了10.0又和8.1不大一样了,最近刚好又用到这个功能,那就整理分享下。

效果图

一级菜单

trKYPe.png

二级菜单

trnUFe.png

文件清单

vendor/mediatek/proprietary/packages/apps/MtkSettings/res/xml/top_level_settings.xml
vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/dashboard/DashboardFragment.java
vendor/mediatek/proprietary/packages/apps/MtkSettings/res/xml/network_and_internet.xml
vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/ethernet/EthernetSettings.java

添加一级菜单

设置主界面对应布局文件为 top_level_settings.xml,里面默认15个 Preference,对应进入设置界面中从上到下

网络和互联网、已连接设备、应用和通知、电池、显示… 也就是说我们在top_level_settings.xml中copy一个

Preference应该就能在主界面显示。

vendor/mediatek/proprietary/packages/apps/MtkSettings/res/xml/top_level_settings.xml

	<Preference
        android:key="top_level_apps_and_notifs"
        android:title="@string/app_and_notification_dashboard_title"
        android:summary="@string/app_and_notification_dashboard_summary"
        android:icon="@drawable/ic_homepage_apps"
        android:order="-100"
        android:fragment="com.android.settings.applications.AppAndNotificationDashboardFragment"/>

	 <Preference
        android:key="level_network"
        android:title="Preference title"
        android:summary="Preference summary"
        android:icon="@drawable/ic_homepage_network"
        android:order="-95"/>

编译替换后发现真的可以,通过设置 order 大小可以调整设置项位置,order绝对值越大越靠上。

如何指定Preference点击后跳转页面呢?

方式一

此种方式比较简单,直接给 Preference 指定 Intent 属性,这里又可以分为 action 和 targetPackage+targetClass 两种方式

<Preference
        android:key="level_network"
        android:title="Preference title"
        android:summary="Preference summary"
        android:icon="@drawable/ic_homepage_network"
        android:order="-95">
         <intent android:action="com.test.settings.first"/>
</Preference>


<Preference
        android:key="level_network"
        android:title="Preference title"
        android:summary="Preference summary"
        android:icon="@drawable/ic_homepage_network"
        android:order="-95">
          <intent
            android:targetPackage="com.android.launcher3"
            android:targetClass="com.android.launcher3.Launcher" />
</Preference>

方式二

略繁琐,找到处理Preference点击逻辑java代码, DashboardFragment 类,这是所有配置项的父类,

点击事件通过 onPreferenceTreeClick() 传递给对应的 AbstractPreferenceController,所以我们可以在

此处拦截处理 level_network 点击事件

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/dashboard/DashboardFragment.java

	@Override
    public boolean onPreferenceTreeClick(Preference preference) {
        Collection<List<AbstractPreferenceController>> controllers =
                mPreferenceControllers.values();
        // If preference contains intent, log it before handling.
        mMetricsFeatureProvider.logDashboardStartIntent(
                getContext(), preference.getIntent(), getMetricsCategory());
		 //cczheng add for customerpreference click
         Log.e(TAG,"keyName="+preference.getKey());
         Log.i(TAG,"size="+controllers.size());

         if(preference.getKey().equals("level_network")){
            Log.e(TAG, "click customer preference....");
            try{
                getContext().startActivity(new android.content.Intent("com.test.settings.first"));
            }catch (Exception e){
                android.widget.Toast.makeText(getContext(), "app don't esxit", 
                    android.widget.Toast.LENGTH_SHORT).show();
            }
            return true;
        }//E
        // Give all controllers a chance to handle click.
        for (List<AbstractPreferenceController> controllerList : controllers) {
            for (AbstractPreferenceController controller : controllerList) {
                if (controller.handlePreferenceTreeClick(preference)) {
                    return true;
                }
            }
        }
        return super.onPreferenceTreeClick(preference);
    }

ok,这样客户只需要在自己 app 的 AndroidManifest.xml 中配置属性给要跳转的Activity即可

<intent-filter>
    <action android:name="com.test.settings.first" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

优化体验

当客户的app不存在时,设置中是没必要添加定制Preference,虽然已经加了容错,异常时 Toast 提示,根据app是否安装来动态显示

这样更合理一些,那么应该怎么做呢?

还是刚刚 DashboardFragment 中,通过判断客户app包名是否存在,不存在则remove Preference。

这里说下为什么是在 DashboardFragment 中,xml 是在 TopLevelSettings 中通过 getPreferenceScreenResId() 加载的,

这是个抽象方法,继承父类 DashboardFragment,在 TopLevelSettings 中获取不到 PreferenceScreen 对象,无法操作

vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/dashboard/DashboardFragment.java

private void displayResourceTiles() {
        final int resId = getPreferenceScreenResId();
        if (resId <= 0) {
            return;
        }
        addPreferencesFromResource(resId);
        final PreferenceScreen screen = getPreferenceScreen();
        screen.setOnExpandButtonClickListener(this);
        mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach(
                controller -> controller.displayPreference(screen));
		//cczheng add check customer app exist
        final Preference preference = findPreference("level_network");
        if (preference != null) {
            if (!checkTilePackage("com.tencent.music")) {
                screen.removePreference(preference);
            }
        }//E
    }


private boolean checkTilePackage(String packageName){
    try { 
           android.content.pm.PackageManager pm =  getContext().getPackageManager();
           pm.getApplicationInfo(packageName, android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES);
           android.util.Log.e("DashboardAdapter", packageName + " app exists show  dashboard");
           return true; 
      }catch (Exception e){ 
          android.util.Log.e("DashboardAdapter", packageName + " app don't exists"); 
          return false; 
      } 
  }

添加二级菜单

这里以添加以太网设置项为例,每个一级设置项对应的布局几乎都是xml文件,找到对应加载xml直接增加即可

vendor/mediatek/proprietary/packages/apps/MtkSettings/res/xml/network_and_internet.xml

<com.android.settingslib.RestrictedPreference
        android:key="mobile_network_settings"
        android:title="@string/network_settings_title"
        android:summary="@string/summary_placeholder"
        android:icon="@drawable/ic_network_cell"
        android:order="-15"
        settings:keywords="@string/keywords_more_mobile_networks"
        settings:userRestriction="no_config_mobile_networks"
        settings:useAdminDisabledSummary="true">
    </com.android.settingslib.RestrictedPreference>

    <!-- cczheng add for ethernet -->
    <com.android.settingslib.RestrictedPreference
        android:key="ethernet_settings"
        android:title="@string/ethernet_settings_title"
        android:summary="@string/summary_placeholder"
        android:icon="@drawable/ic_ethernet_cell"
        android:fragment="com.android.settings.ethernet.EthernetSettings"
        android:order="-17"/>

通过指定 fragment 属性跳转对应页面,新增对应跳转实现类ok

总结

静态方式增加配置项耦合性较强,APP Action 或包名都需要配置到 Settings 源码中,不灵活。

下篇介绍通过动态方式添加配置项

猜你喜欢

转载自blog.csdn.net/u012932409/article/details/106574155