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 源碼中,不靈活。

下篇介紹通過動態方式添加配置項

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章